leetcode:219. 存在重复元素 II

题目来源

leetcode

题目描述

在这里插入图片描述

题目解析

哈希表

从左到右遍历数组nums,当遍历到下标 i i i时,如果存在下标 j < i j < i j<i使得 n u m s [ i ] = = n u m s [ j ] nums[i] == nums[j] nums[i]==nums[j],则当 i − j < = k i - j <= k ij<=k时即找到了两个符号要求的下标j和i。

如果在下标 i i i之前存在多个元素都和 n u m s [ i ] nums[i] nums[i]相等,为了判断是否存在满足 n u m s [ i ] = = n u m s [ j ] nums[i] == nums[j] nums[i]==nums[j]而且 i − j < = k i - j <= k ij<=k的下标 j j j,应该在这些元素中寻找下标最大的元素,将最大下标记为 j j j,判断 i − j < = k i - j <= k ij<=k是否成立。

  • 如果 i − j < = k i - j <= k ij<=k,则找到了两个符合要求的下标 j 和 i;
  • 如果 i − j > k i - j > k ij>k,则在下标 i i i之前不存在任何元素满足与nums[i]相等而且下标差的绝对值不超过 k k k

因此,当遍历到下标i时,如果在下标i之前存在于 n u m s [ i ] nums[i] nums[i]相等的元素,应该在这些元素中寻找最大的下标j,判断 i − j < = k i - j <= k ij<=k是否成立。

可以使用哈希表记录每个元素的最大下标。从左到右遍历数组nums,当遍历到下标i时,进行如下操作:

  • 如果哈希表中已经存在和 n u m s [ i ] nums[i] nums[i]相等的元素而且该元素在哈希表中记录的下标 j j j满足 i − j < = k i - j <= k ij<=k,返回true
  • n u m s [ i ] nums[i] nums[i]和下标 i i i存入哈希表,此时i是 n u m s [ i ] nums[i] nums[i]的最大下标

上面两步操作的顺序不能改变,因为当遍历到下标 i i i时,只能在下标 i i i之前的元素中寻找与当前元素相等的元素以及该元素的最大下标

当遍历结束时,如果没有遇到两个相等元素的下标差的绝对值不超过k,返回false

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        std::unordered_map<int, int> map;
        for (int i = 0; i < nums.size(); ++i) {
            auto it = map.find(nums[i]);
            if(it != map.end() && i - it->second <= k ){
                return true;
            }else{
                 map[nums[i]] = i;
            }
        }

        return false;
    }
};

在这里插入图片描述
复杂度分析:
在这里插入图片描述

滑动窗口

考虑数组nums中的每个长度不超过 k + 1 k + 1 k+1的滑动窗口,同一个滑动窗口中的任意两个下标差的绝对值不超过k。

  • 如果存在一个滑动窗口,其中有重复元素,则存在两个不同的下标 i i i j j j满足 n u m s [ i ] = n u m s [ j ] nums[i] = nums[j] nums[i]=nums[j]而且 ∣ i − j ∣ < = k |i - j| <= k ij<=k
  • 如果所有滑动窗口中都没有重复元素,则不存在符合要求的下标。

因此,只要遍历每个滑动窗口,判断滑动窗口中是否有重复元素即可。

如果一个滑动窗口的结束下标是 i i i,则该滑动窗口的开始下标是 m a x ( 0 , i − k ) max(0, i-k) max(0,ik)。可以使用哈希集合存储滑动窗口中的元素。从左到有遍历数组 n u m s nums nums,当遍历到下标 i i i时,具体操作如下:

  • 如果 i > k i > k i>k,则下标 i − k − 1 i - k - 1 ik1处的元素被移除滑动窗口,因此将nums[i - k - 1]从哈希集合中删除、
  • 判断nums[i]是否在哈希集合中,如果在哈希集合中则在同一个滑动窗口中有重复元素,返回 true,如果不在哈希集合中则将其加入哈希集合

当遍历结束时,如果所有滑动窗口中都没有重复元素,返回false

bool containsNearbyDuplicate(vector<int>& nums, int k) {
    std::unordered_set<int> s;
    for (int i = 0; i < nums.size(); ++i) {
        if(i > k){
            s.erase(nums[i - k - 1]);
        }
        
        if(s.count(nums[i])){
            return true;
        }
        s.emplace(nums[i]);
    }

    return false;
}


在这里插入图片描述

复杂度分析:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值