一、代码描述
给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。
如果存在则返回 true,不存在返回 false。
输入:nums = [1,2,3,1], k = 3, t = 0 输出:true
二、代码思路
本题可以转换为:在下标j的前K个元素中,有没有符合abs(nums[i] - nums[j]) <= t的情况
上述的公式也可以转换为(把绝对值去掉):-t <= numsi - numsj <= t 进一步转换:numsi - t <= numsj <= numsi + t。
所以,是不是有这样一种想法:把j的前k个元素放到一个数据结构中,然后我们只需要从中取出来一个大于numsi的最小元素,然后判断是否符合上述两个式子即可。
为什么我们只需要从中取出来一个大于numsi - t 的最小元素呢?
因为 t是正的,所以只有取出numsj越小,在给定的numsi的上述不等式中 numsj才能符合。
同时我们还要保证加入集合中的元素的下标是符合abs(i - j) <= k的也就是: i j 都是正的,i > k 的时候,需要把 小于 i - k的元素都删掉,i < k的时候,由于i是从i = 0,逐步递增的。
所以,就算只维护左侧的k的窗口也是可以的,因为由于绝对值的特殊性,当numi 和 numj互换也没问题,就是说num[i] - nums[j] 就算交换相减也没问题,所以并没有丢失右侧的numj。
三、代码思路
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
int n = nums.length;
TreeSet<Long> set = new TreeSet();
for (int i = 0; i < n; i++) {
Long ceil = set.ceiling((long) nums[i] - (long) t);
if (ceil != null && ceil <= (long) nums[i] + (long) t) {
return true;
}
set.add((long) nums[i]);
if (i >= k) {
set.remove((long) nums[i - k]);
}
}
return false;
}
}
|