「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」。
题目描述🌍
给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。
示例 1:
输入:nums = [1,2,3,1], k = 3
输出:true
示例 2:
输入:nums = [1,0,1,1], k = 1
输出:true
示例 3:
输入:nums = [1,2,3,1,2,3], k = 2
输出:false
提示:
- 1 <=
nums.length<= 105 - -109 <=
nums[i]<= 109 - 0 <=
k<= 105
滑动窗口 & 哈希表🚀
先来点真实的暴力求解🥴:
💭想想新出路..
解题思路
维护一个容量为 k + 1 的滑动窗口,遍历数组并添加元素,若在滑动窗口添加元素过程中发现相同元素,则表明找到 return true。
需要注意的是:
- 在添加前
k个元素时,滑动窗口仍未饱和,此时直接添加即可; - 在添加元素
nums[k+1]后,窗口饱和,此后都需要剔除此刻滑动窗口中最早添加的元素nums[i-k],为下一个元素腾出空间。
代码
Java
7 - 9 行代码可简化为:
if (!hashSet.add(nums[i])) { return true; }
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
// 维护一个 k+1 容量的哈希表,一旦出现 false 表明在 k+1 范围内存在重复元素
Set<Integer> hashSet = new HashSet<>();
int length = nums.length;
for (int i = 0; i < length; i++) {
if (hashSet.contains(nums[i]))
return true;
hashSet.add(nums[i]);
// 固定窗口, 清空超出窗口的元素
if (hashSet.size() == k + 1)
hashSet.remove(nums[i - k]);
}
// 遍历数组没有找到符合条件的重复元素
return false;
}
}
C++
class Solution {
public:
bool containsNearbyDuplicate(vector<int> &nums, int k) {
unordered_set<int> duplicate;
int length = nums.size();
for (int i = 0; i < length; i++) {
if (duplicate.find(nums[i]) != duplicate.end())
return true;
duplicate.insert(nums[i]);
if (duplicate.size() == k + 1)
// 移除此刻滑动窗口中最早添加的元素
duplicate.erase(nums[i - k]);
}
return false;
}
};
时间复杂度:
空间复杂度:
最后🌅
该篇文章为 「LeetCode」 系列的 No.18 篇,在这个系列文章中:
- 尽量给出多种解题思路
- 提供题解的多语言代码实现
- 记录该题涉及的知识点
👨💻争取做到 LeetCode 每日 1 题,所有的题解/代码均收录于 「LeetCode」 仓库,欢迎随时加入我们的刷题小分队!