LeetCode笔记:存在重复元素 II
问题
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
示例 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
解法一
思路:
用一个对象来存储每个数字的信息,利用 key 不能重复的原理,每次遇到新的重复的数字,就更新位置信息和最近一个重复数字的绝对值,一旦遇到一个绝对值比k
小就是成功找到了想要的数字。
代码:
/**
* @param {number[]} nums
* @param {number} k
* @return {boolean}
*/
var containsNearbyDuplicate = function (nums, k) {
// 初始化存储空间
const obj = {};
// 一遍循环即可,遍历所有的数字
for (let i = 0; i < nums.length; i++) {
// 当前数字
const n = nums[i];
// 是否出现重复数字
if (n in obj) {
// 重复出现的数字,绝对值需要更新为和前一个值的差,因为和前一个的差肯定更小
obj[n].abs = i - obj[n].i;
// 上面计算完差值,就可以更新当前位置了,用于下一次重复出现的时候计算差值
obj[n].i = i;
// 一旦发现当前差值小于k,即满足条件退出
if (obj[n].abs <= k) return true;
} else {
// 第一次出现的数字进行初始化,存储位置和绝对值(因为第一次出现,所以绝对值为0)
obj[n] = {
i: i,
abs: 0,
};
}
}
//如果上面的循环中没有找到满足条件的数字,默认返回`false`
return false;
};
解法二
思路:
利用Set
不允许重复元素的特性,做一个k
大小的滑动窗口,一直往前滑动寻找窗口内是否出现相同元素。这个滑动窗口需要的空间更小。
代码:
/**
* @param {number[]} nums
* @param {number} k
* @return {boolean}
*/
var containsNearbyDuplicate = function (nums, k) {
const set = new Set();
for (let i = 0; i < nums.length; i++) {
// 滑动窗口内一旦出现重复元素,即满足要求
if (set.has(nums[i])) {
return true;
}
// 每个值都加入
set.add(nums[i]);
// 一旦数量超出k,就删除第一个数字,即滑动窗口右移
if (set.size > k) {
set.delete(nums[i - k]);
}
}
return false;
};
评论