220. 存在重复元素 III去力扣刷题吧!
在整数数组 nums 中,是否存在两个下标 i 和 j
–> ① nums[i] 和 nums[j] 的差的绝对值小于等于 t
–> ② 且 i 和 j 的差的绝对值也小于等于 k 。

问题分析
方法一. 滑动窗口 + TreeSet
- 由于在数组中需要满足两个下标的距离在
k范围呢,因此可以结合滑动窗口的思想,只是这边的滑动窗口固定了窗口大小为k + 1,我们用一个TreeSet维护该窗口,当新加入元素num时,判断窗口中是否有元素在[num - t, num + t]范围内,有则返回true,无则将num加入窗口,同时移出最左侧的元素。 - TreeSet的妙用:
set.ceiling(num)Treeset中的上限函数,该方法可以返回一个set中大于等于num的最小值,在判断窗口中是否有元素在[num - t, num + t]范围内若存在一个值在该范围内即可返回true
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
//采用long是因为测试用例中有Integer越界问题
TreeSet<Long> set = new TreeSet<>();
int n = nums.length;
for (int i = 0; i < n; i++) {
if (i > k) {
set.remove((long)nums[i - k - 1]);
}
// ceiling Treeset中的上限函数,set中大于某个值的最小值
Long low = set.ceiling((long) nums[i] - t);
//是否找到了符合条件的数
if (low != null && low <= (long)nums[i] + t) {
return true;
}
set.add((long) nums[i]);
}
return false;
方法二. 桶排序
- 同时仍是基于滑动窗口的思想。
- 我们将每个桶的大小设置为
t + 1,每次判断当前num需要放进的桶编号中是否有值,或者相邻的桶中是否有元素在[num - t, num + t]范围内。使用map存储,key表示桶编号,value表示桶中已存在的数字。 - 同时在移动过程中需要将
i - k - 1的值移出桶外,因为该值已经不会影响到当前num值 - 获取桶编号采用
num / (t + 1)的方式,但是在数组中存在负数的情况,则会存在靠近0的负数/ (t + 1)时桶编号也为0, 因此采用(num + 1) / (t + 1) - 1
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (t < 0) {
return false;
}
HashMap<Long, Long> map = new HashMap<>();
int n = nums.length;
long w = t + 1; // 一个桶里边数字范围的个数是 t + 1
for (int i = 0; i < n; i++) {
//删除窗口中第一个数字
if (i > k) {
map.remove(getId(nums[i - k - 1], w));
}
//得到当前数的桶编号
long id = getId(nums[i], w);
//当前桶中已有值
if (map.containsKey(id)) {
return true;
}
//相邻的桶中有在[num - t, num + t]内
if (map.containsKey(id + 1) && map.get(id + 1) - nums[i] < w) {
return true;
}
if (map.containsKey(id - 1) && nums[i] - map.get(id - 1) < w) {
return true;
}
map.put(id, (long) nums[i]);
}
return false;
}
private long getId(long num, long w) {
if (num >= 0) {
return num / w;
} else {
return (num + 1) / w - 1;
}
}
复杂度分析
- 滑动窗口+TreeSet:
O(nlog(k))
TreeSet的ceiling方法的时间复杂度都是O(log(n)) - 桶排序:
O(n)
在HashMap中取值是常数级的,同时我们只需要遍历一遍数组
本文深入解析力扣第220题“存在重复元素III”,探讨在数组中寻找两个元素,其差的绝对值及下标差的绝对值分别满足特定条件的算法策略。重点介绍了两种高效解决方案:滑动窗口+TreeSet与桶排序。
881

被折叠的 条评论
为什么被折叠?



