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.
classSolution{publicbooleancontainsNearbyAlmostDuplicate(int[]nums,intk,intt){if(nums ==null||nums.length<2)returnfalse;TreeSet<Integer> treeset =newTreeSet<>();int i =0, j =1;treeset.add(nums[0]);while(j <nums.length){if(j - i > k){treeset.remove(nums[i]);// 窗口 left 右移,删去出去的num i++;}if(treeset.ceiling(nums[j])!=null&&Math.abs((long)treeset.ceiling(nums[j])-(long)nums[j])<= t)returntrue;// check successorif(treeset.floor(nums[j])!=null&&Math.abs((long)treeset.floor(nums[j])-(long)nums[j])<= t)returntrue;// check predecessortreeset.add(nums[j]); j++;}returnfalse;}}
思路 2:Bucket 每个 bucket 的size为 t,维持这个buckets,每次右边刚进入窗口的数 m,我们检查 m 所在bucket中是否有元素,若没有,则检查 m 所在bucket的左边和右边相邻有无元素即可。
时间: O(n)
Python Code:
update 2018-07-21 17:27:05
Update Bucket sort solution
思路如下:
先将input array normalize 为 最小值为 0 的数组;
用一个hashMap来存放buckets,bucket index = num / (t + 1);
保持 window size 为 k + 1,每次查看当前数字对应 bucket index 是否已有元素,若有,则该元素与当前数字的绝对值差一定小于等于 t,直接返回true;否则的话,查看 index - 1 和 index + 1 两个buckets,看其中的元素和当前数字的距离是否小于等于 t;
class Solution(object):
def containsNearbyAlmostDuplicate(self, nums, k, t):
"""
:type nums: List[int]
:type k: int
:type t: int
:rtype: bool
"""
def getIndex(num):
if t == 0: return num - t
return (num - t) // t
if not nums or len(nums) < 2 or k < 1 or t < 0:
return False
buckets = {} # Map<index, num> 因为每个bucket只能有一个数字(出现两个就返回true了)
buckets[getIndex(nums[0])] = nums[0]
i, j = 0, 1
while j < len(nums):
if j - i > k:
del buckets[getIndex(nums[i])]
i += 1
index = getIndex(nums[j])
if index in buckets:
return True
if index - 1 in buckets and abs(buckets[index - 1] - nums[j]) <= t:
return True
if index + 1 in buckets and abs(buckets[index + 1] - nums[j]) <= t:
return True
buckets[index] = nums[j]
j += 1
return False
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (t < 0) return false;
// normalize first
long[] longNums = new long[nums.length];
long min = Integer.MAX_VALUE;
for (int num : nums) {
min = Math.min(min, num);
}
for (int i = 0; i < nums.length; ++i) longNums[i] = (long)nums[i] - min;
Map<Long, Long> buckets = new HashMap<>();
int left = 0, right = -1;
while (true) {
while (right - left + 1 < k + 1) {
if (right == nums.length - 1) return false;
long num = longNums[++right];
long index = num / (t + 1);
if (buckets.containsKey(index)) return true;
Long prev = buckets.get(index - 1);
Long next = buckets.get(index + 1);
if (prev != null && Math.abs(num - prev) <= t) return true;
if (next != null && Math.abs(num - next) <= t) return true;
buckets.put(index, num);
}
buckets.remove(longNums[left++] / (t + 1));
}
}
}