您的位置:首页 > 大数据 > 人工智能

220. Contains Duplicate III

2016-06-26 17:04 477 查看
Given an array of integers, find out whether there are two distinct indices i and j in
the array such that the difference between nums[i] and nums[j] is
at most t and
the difference between i and j is
at most k.

K小的时候在index<=K范围内检测是否有和当前元素相差t 以内(临近)的元素,K大的时候以当前元素正负t为范围在hashmap扫描是否重复。

这思路有些投机取巧的意思。

public static boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t)
{
int len=nums.length;
if(len<=1)
return false;
HashMap<Integer, Integer> hashmap=new HashMap<>(len);

for(int i=0;i<len;i++)
{
long num=nums[i];

if(k<=100)
for(int m=Math.max(i-k,0);m<i;m++)
{
long prenum=hashmap.get(m);
if(prenum>=num-t&&prenum<=num+t)
return true;
}
else
{
for(long m=num-t;m<=num+t;m++)
if(hashmap.containsKey(m)&&i-hashmap.get(m)<=k)
return true;
}

hashmap.put(i, (int) num);
}
return false;
}


更好的方法,摘自
https://discuss.leetcode.com/topic/15199/ac-o-n-solution-in-java-using-buckets-with-explanation https://discuss.leetcode.com/topic/15191/java-o-n-lg-k-solution
-------------------------------------------------------------------------------------------------------------------------

As a followup question, it naturally also requires maintaining a window of size k. When t == 0, it reduces to the previous question so we just reuse the solution.

Since there is now a constraint on the range of the values of the elements to be considered duplicates, it reminds us of doing a range check which is implemented in tree data structure and would take O(LogN) if a balanced tree structure is used, or doing a
bucket check which is constant time. We shall just discuss the idea using bucket here.

Bucketing means we map a range of values to the a bucket. For example, if the bucket size is 3, we consider 0, 1, 2 all map to the same bucket. However, if t == 3, (0, 3) is a considered duplicates but does not map to the same bucket. This is fine since we
are checking the buckets immediately before and after as well. So, as a rule of thumb, just make sure the size of the bucket is reasonable such that elements having the same bucket is immediately considered duplicates or duplicates must lie within adjacent
buckets. So this actually gives us a range of possible bucket size, i.e. t and t + 1. We just choose it to be t and a bucket mapping to be num / t.

Another complication is that negative ints are allowed. A simple num / t just shrinks everything towards 0. Therefore, we can just reposition every element to start from Integer.MIN_VALUE.
public class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (k < 1 || t < 0) return false;
Map<Long, Long> map = new HashMap<>();
4000
for (int i = 0; i < nums.length; i++) {
long remappedNum = (long) nums[i] - Integer.MIN_VALUE;
long bucket = remappedNum / ((long) t + 1);
if (map.containsKey(bucket)
|| (map.containsKey(bucket - 1) && remappedNum - map.get(bucket - 1) <= t)
|| (map.containsKey(bucket + 1) && map.get(bucket + 1) - remappedNum <= t))
return true;
if (map.entrySet().size() >= k) {
long lastBucket = ((long) nums[i - k] - Integer.MIN_VALUE) / ((long) t + 1);
map.remove(lastBucket);
}
map.put(bucket, remappedNum);
}
return false;
}
}


Edits:

Actually, we can use t + 1 as the bucket size to get rid of the case when t == 0. It simplifies the code. The above code is therefore the updated version.

-----------------------------------------------------------------------------------------------------

This problem requires to maintain a window of size k of the previous values that can be queried for value ranges. The best data structure to do that is Binary Search Tree. As a result maintaining the tree of size k will result in time complexity O(N lg K).
In order to check if there exists any value of range abs(nums[i] - nums[j]) to simple queries can be executed both of time complexity O(lg K)

Here is the whole solution using TreeMap.
public class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (nums == null || nums.length == 0 || k <= 0) {
return false;
}

final TreeSet<Integer> values = new TreeSet<>();
for (int ind = 0; ind < nums.length; ind++) {

final Integer floor = values.floor(nums[ind] + t);
final Integer ceil = values.ceiling(nums[ind] - t);
if ((floor != null && floor >= nums[ind])
|| (ceil != null && ceil <= nums[ind])) {
return true;
}

values.add(nums[ind]);
if (ind >= k) {
values.remove(nums[ind - k]);
}
}

return false;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: