Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.
Example 1:
Input: nums = [1,2,3,1], k = 3, t = 0 Output: true
Example 2:
Input: nums = [1,0,1,1], k = 1, t = 2 Output: true
Example 3:
Input: nums = [1,5,9,1,5,9], k = 2, t = 3 Output: false
这一题和Contains Duplicate II的思路实际上是完全不同的。我的解法对于这一题来说就是维护一个大小为k的window,这个window的所有数字都放在一个叫TreeSet的无敌的数据结构里。这个无敌的数据结构里有两个函数,一个叫higher,这个函数会返回放在这个TreeSet里大于给定目标的最小数(如果存在,否则返回null),另一个叫lower,这个函数会返回这个TreeSet里小于给定目标的最大数(如果存在,否则null)。所以顺序遍历数组,一边看TreeSet的三样东西:1. 是否存在当前数字(是就直接返回true),2. higher,3. lower。 看看2和3取得的数字是否在范围t之内。同时维护TreeSet所代表的window。 总体算法复杂度是O(nlogk),因为TreeSet的最大size为k,所以每一次的操作复杂度为logk而非logN
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (k <= 0 || t < 0) return false;
TreeSet<Long> numSet = new TreeSet<Long>();
for (int i = 0; i < nums.length; i++) {
Long higher = numSet.higher((long)nums[i]);
Long lower = numSet.lower((long)nums[i]);
long diff = numSet.contains((long)nums[i]) ? 0 : Long.MAX_VALUE;
diff = higher != null ? Math.min(higher - (long)nums[i], diff) : diff;
diff = lower != null ? Math.min((long)nums[i] - lower, diff) : diff;
if (diff <= (long)t) return true;
if (i >= k) {
numSet.remove((long)nums[i - k]);
}
numSet.add((long)nums[i]);
}
return false;
}