给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。
示例 1:
输入: nums = [1,2,3,1], k = 3, t = 0
输出: true
示例 2:
输入: nums = [1,0,1,1], k = 1, t = 2
输出: true
示例 3:
输入: nums = [1,5,9,1,5,9], k = 2, t = 3
输出: false
思路:
首先会想到的是通过窗口的滑动来判断,但是时间复杂度太高了,超时。
第二种思路,是采用桶排序的思想,分析题目可知需要在k大小的窗口上找到两个数的差要小于t,
所以就可以将数分桶,桶大小为t,若存在两个数在一个桶范围内,则满足要求,
还有一种情况在相邻桶之间存在两个数的差小于等于t。
代码:
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
//使用哈希表来做桶存储元素
Map<Long, Long> map = new HashMap<>();
long w = (long)t + 1;
for (int i = 0; i < nums.length; i++) {
long id = getId(nums[i], w);
//在桶中已经存在了
if (map.containsKey(id)) {
return true;
}
//判断相邻桶
if (map.containsKey(id - 1) && Math.abs(map.get(id - 1) - nums[i]) < w) {
return true;
}
if (map.containsKey(id + 1) && Math.abs(map.get(id + 1) - nums[i]) < w) {
return true;
}
map.put(id, (long)nums[i]);
if (i >= k){ // 保持窗口太小为k
map.remove(getId(nums[i - k], w));
}
}
return false;
}
//计算数所在桶的id
private long getId(int i, long w) {
return i < 0 ? (i + 1) / w - 1 : i / w;
}
}