力扣LeetCode: 219 存在重复元素Ⅱ

新年快乐!!!

题目:

        给你一个整数数组 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

解法:滑动窗口

1. 滑动窗口

滑动窗口是一种动态维护一个固定大小范围的技巧。在这个问题中,窗口的大小为 k + 1,因为我们需要检查的是索引差是否小于等于 k

  • 窗口的范围是当前元素及其前 k 个元素。

  • 如果在这个窗口内发现重复元素,则说明存在满足条件的索引对。

2. 哈希表

哈希表(std::unordered_set)用于快速查找和存储窗口内的元素。它的特点是:

  • 插入和查找的平均时间复杂度为 O(1)。

  • 可以高效地判断一个元素是否已经存在于窗口中。

解决策略

  1. 初始化

    • 创建一个空的哈希表 window,用于存储当前窗口内的元素。

    • 遍历数组 nums,逐个检查每个元素。

  2. 检查重复

    • 对于当前元素 nums[i],检查它是否已经存在于 window 中。

    • 如果存在,说明找到了满足条件的重复元素,返回 true

  3. 维护窗口

    • 将当前元素 nums[i] 插入到 window 中。

    • 如果窗口的大小超过了 k + 1,则移除窗口最左边的元素(即 nums[i - k]),以保持窗口的大小不超过 k + 1

  4. 返回结果

    • 如果遍历完数组后没有找到满足条件的重复元素,则返回 false

class Solution {
public:
    bool containsNearbyDuplicate(std::vector& nums, int k) {
        std::unordered_set window; // 滑动窗口,存储当前窗口内的元素

        for (int i = 0; i < nums.size(); ++i) {
            // 如果当前元素已经在窗口中,说明存在满足条件的重复元素
            if (window.find(nums[i]) != window.end()) {
                return true;
            }

            // 将当前元素加入窗口
            window.insert(nums[i]);

            // 维护窗口大小不超过 k + 1
            if (window.size() > k) {
                window.erase(nums[i - k]); // 移除窗口最左边的元素
            }
        }

        return false; // 没有找到满足条件的重复元素
    }
};
1. 时间复杂度
  • 遍历数组的时间复杂度为 O(n),其中 n 是数组的长度。

  • 每个元素的插入和查找操作在哈希表中的平均时间复杂度为 O(1)。

  • 因此,总的时间复杂度为 O(n)

2. 空间复杂度
  • 使用了一个哈希表 window 来存储窗口内的元素。

  • 窗口的大小最多为 k + 1,因此空间复杂度为 O(min(n, k))。

你可能感兴趣的:(LeetCode,leetcode,算法,数据结构)