【每日算法】存在重复元素Ⅱ

87 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

存在重复元素Ⅱ

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。

示例1

输入:nums = [1, 2, 3, 1], k = 3
输出:true
  • 可以发现输入的数组中,满足题目要求(两个数字相等)的只有两个 1
  • 它们的索引分别是 0 和 3,满足差值小于等于 k (3) 的条件,所以输出为 true

示例2

输入:nums = [1, 2, 3, 1, 2, 3], k = 2
输出:false
  • 输入的数字中有三组相同的数字(1、2、3)
  • 他们的索引差值都是 3,都不满足 <= k 的条件,所以返回 false

方法1:暴力解

根据题目意思,我们需要从数组中获取两个相同的值,并且判断他们的索引差值是否满足小于等于 k 的条件

可以利用双循环来锁定两个值

  • 第一层遍历 nums 数组的每一个元素,拿到第一个元素
  • 第二层遍历第一个元素后面的每一个元素,找到相同的元素,进行条件对比
var containsNearbyDuplicate = function(nums, k) {
  for(let i=0; i<nums.length; i++) { // 第一层遍历,获取第一个数值
    for(let j=i+1; j<nums.length; j++) { // 第二层遍历从 i 的后面一位开始,因为前面的已经找过了
      if(nums[i] === nums[j] && Math.abs(i-j) <= k) {
        // 两个数值相等,并且索引差值小于等于 k
        return true
      }
    }
  }
  return false
}

方法2:滑动窗口

  • 维护一个区间,里面始终最多包含 k 个元素,当出现重复值时则说明在 k 距离内存在重复元素,返回 true
  • 每次遍历到一个元素,则将其加入区间
  • 如果区间的大小大于 k 了,则移除最前面的数字
var containsNearbyDuplicate = function(nums, k) {
  const set = new Set()
  for(let i=0; i<nums.length; i++) { // 遍历数组
    if(set.has(nums[i])) { 
      // 当前遍历到的数字已经存在于Set中了。
      // 边界条件:假设k=2,并且当前set中也已经有2个元素了,此时出现重复。[1,2] 出现 1,则相隔距离为2,满足条件
      return true
    }
    set.add(nums[i])
    if(set.size > k) { // 确保set中只有k个元素
      set.delete(nums[i-k])
    }
  }
  return false
}