「前端刷题」220.存在重复元素 III(MEDIUM)

93 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情

题目(Contains Duplicate III)

链接:https://leetcode-cn.com/problems/contains-duplicate-iii
解决数:567
通过率:29.1%
标签:数组 桶排序 有序集合 排序 滑动窗口 
相关公司:google amazon bytedance 

给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k **。

如果存在则返回 true,不存在返回 false

 

示例 1:

输入: nums = [1,2,3,1], k = 3, t = 0
输出: true

示例 2:

输入: nums = [1,0,1,1], k = 1, t = 2
输出: true

示例 3:

输入: nums = [1,5,9,1,5,9], k = 2, t = 3
输出: false

 

提示:

  • 0 <= nums.length <= 2 * 104
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 104
  • 0 <= t <= 231 - 1

思路

请看代码

代码

/**
 * @param {number[]} nums
 * @param {number} k
 * @param {number} t
 * @return {boolean}
 */
var containsNearbyAlmostDuplicate = function (nums, k, t) {
    function getId(x) {
        return Math.floor(x / (t + 1));
    }
    if (t < 0) return false;

    // 大桶,里面最多有k个小桶。(超过k的时候会删除第一个小桶,滑动窗口的概念
    const map = new Map();

    for (let i = 0; i < nums.length; i++) {
        // m是当前遍历元素将要在的桶
        const m = getId(nums[i]);

        // 当前大桶中有这个小桶的话,说明存在重复且符合条件,下面两个条件也一样。每次会对比桶的左右小桶。
        if (map.has(m)) {
            return true;
            // 如果当前小桶的右边桶存在,且两个桶相差小于t
        } else if (map.has(m + 1) && Math.abs(map.get(m + 1) - nums[i]) <= t) {
            return true;
            // 如果当前小桶的左边桶存在,且两个桶相差小于t
        } else if (map.has(m - 1) && Math.abs(map.get(m - 1) - nums[i]) <= t) {
            return true;
        }
        // 将这个桶存到大桶里面
        map.set(m, nums[i]);
        // 如果i大于k,也就是大桶装满了,则需要把大桶里面的第一个小桶删了。
        if (i >= k) {
            map.delete(getId(nums[i - k]));
        }
    }
    return false;
};
  • 一直在纠结-0 === 0 为true这个问题,最后觉得只要向下取整其实也可以解决这个问题
  • 不一定用map,用最简单的对象当然也行
/**
 * @param {number[]} nums
 * @param {number} k
 * @param {number} t
 * @return {boolean}
 */
var containsNearbyAlmostDuplicate = function(nums, k, t) {
    // 解决js中 -0 === 0 为true的问题
    function getId(x, w) {
        return Math.floor(x / w)
    }
    if (t < 0) return false
    const map = new Map()
    const w = t + 1
    for (let i = 0; i < nums.length; i++) {
        const m = getId(nums[i] ,w)
        if (map.has(m)) return true
        else if (map.has(+m + 1) && Math.abs(map.get(+m + 1) - nums[i]) < w) return true
        else if (map.has(+m - 1) && Math.abs(map.get(+m - 1) - nums[i]) < w) return true
        map.set(m, nums[i])
        if (i >= k) map.delete(getId(nums[i - k], w))
    }
    return false
};