LeetCode:219.存在重复元素||220.存在重复元素|||
题目要求nums[i] == nums[j]
且 abs(i - j) <= k,其实就是维护一个长为
abs(i - j)的窗口,存在nums[i] == nums[j]。此题我们可以用滑动窗口来解决,枚举右边维护左边。
C++代码:
class Solution {
public:bool containsNearbyDuplicate(vector<int>& nums, int k) {unordered_set<int> window; // 存储当前窗口内的元素int n = nums.size();for (int right = 0; right < n; right++) {// 若窗口大小超过k,移除左边界元素(保证窗口内元素下标差 <=k)if (right > k) {window.erase(nums[right - k - 1]); // 移除窗口外的左元素}// 若当前元素在窗口中存在,说明找到符合条件的重复元素if (window.count(nums[right])) {return true;}// 将当前元素加入窗口window.insert(nums[right]);}// 遍历完未找到return false;}
};
unordered_set
用 O (1) 时间快速判断元素的存在性,一旦出现重复,直接返回结果,无需存储重复元素。
220.也是同理,维护的是一个 长为
abs(i - j)的窗口。只不过窗内存在的条件不同:
C++代码:
class Solution {
public:bool containsNearbyAlmostDuplicate(vector<int>& nums, int indexDiff, int valueDiff){ set<int> m;int n = nums.size();for (int right = 0; right < n; right++) // 固定窗口{if (right > indexDiff)m.erase(nums[right - indexDiff - 1]);int tar = nums[right];auto it = m.lower_bound(tar - valueDiff);if (it != m.end() && *it <= tar + valueDiff)return true;m.insert(tar);}return false;}
};
set
基于红黑树实现,元素会按照默认的比较规则有序存储,时间复杂度为 O(log n)。此题可以利用其 “有序性” 相关的范围查询很方便来解决abs(nums[i] - nums[j]) <= valueDiff。
总结:
当问题涉及连续的子数组、子串或区间,且需要对区间内的元素进行整体处理(如求和、计数、判断是否满足条件)时,我们就可以优先使用滑动窗口。