/** * https://leetcode.cn/problems/contains-duplicate-ii/?envType=study-plan-v2&envId=top-interview-150 * @param {number[]} nums * @param {number} k * @return {boolean} */ const containsNearbyDuplicate = function (nums, k) { }; /* 定义两个指针表示abs(i - j) <= k的窗口,i向右移动,查看当前指向的值在set中是否存在,不存在就把这个值存入set,如果i-j >k 表明 当前太大了,要缩小,把j指向的元素从set中剔除掉,i++,并将测j指向的值是否在set中存在 */ function f1(nums, k) { const set = new Set(); for (let i = 0, j = 0; i < nums.length; i++) { // 如果 窗口太大,就缩小窗口再检测 if (i - j > k) { set.delete(nums[j]); j++; } // 检测 nums[i]是否在set中存在 if (set.has(nums[i])) return true; // 将当前值存入set set.add(nums[j]); } return false; } /* 优化,上面代码中i-jk时i-j一定大于k,因为后续我们会一个值一个值的检测,例如:当k=3,i=4时,这个时候 一定要缩小串口,直接剔除掉i-k-1表示的元素即可,set中剩下的元素还是4个,这样可以少用一个下标,判断也更快 */ function f2(nums, k) { const set = new Set(); for (let i = 0; i < nums.length; i++) { // 超出滑动窗口 if (i > k) { set.delete(nums[i - k - 1]); } // 检测set中是否含有这个元素 if (set.has(nums[i])) return true; set.add(nums[i]); } return false; } /* 直接一次遍历,利用map储存之前遍历的所有值和下标,如果当前值在map中存在,并且当前值的下标减去map中对应值的小标,结果小于等于k 则表明发生了重复 */ function f3(nums, k) { const map = new Map(); for (let i = 0; i < nums.length; i++) { const num = nums[i]; if (map.has(num) && i - map.get(num) <= k) return true; map.set(num, i); } return false; }