「LeetCode」219.存在重复元素 II

318 阅读1分钟

「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」。

题目描述🌍

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个不同的索引 ij ,满足 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;
    }
};

时间复杂度:O(n)O(n)

空间复杂度:O(k)O(k)

最后🌅

该篇文章为 「LeetCode」 系列的 No.18 篇,在这个系列文章中:

  • 尽量给出多种解题思路
  • 提供题解的多语言代码实现
  • 记录该题涉及的知识点

👨‍💻争取做到 LeetCode 每日 1 题,所有的题解/代码均收录于 「LeetCode」 仓库,欢迎随时加入我们的刷题小分队!