LeetCode.219 存在重复元素 II

245 阅读2分钟

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

题目描述:

219. 存在重复元素 II - 力扣(LeetCode) (leetcode-cn.com)

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 ij 的差的 绝对值 至多为 k

示例一

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

示例二

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

示例三

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

思路分析

用散列表来维护一个 k 大小的滑动窗口。

我们来把题目的描述转换下

找到 i 和 j,使得 nums [i] = nums [j],并且 ij 的差的 绝对值 至多为 k

⬇⬇⬇

在一个大小为 k 的区间里,看下存不存在两个数相同。

这个 大小为 k 的区间 我们有好几种方法去实现。 这个区间我们可以理解为 算法中常见的 "窗口"。

image.png

假设 k =3 我们就有一个长度为3的这么一个窗口,我们从最左边一直往右移,去看这个窗口(框里)有没有相同的数字,这样就很好理解了吧。

再生动点,可以参考下这个老哥的动画

AC代码

class Solution {
    fun containsNearbyDuplicate(nums: IntArray, k: Int): Boolean {
        val window = mutableSetOf<Int>()
        for (i in 0..nums.lastIndex) {
            if (!window.add(nums[i])) {
                return true
            }
            if(window.size > k) {
                window.remove(nums[i - k])
            }
        }
        return false
    }
}

线性搜索

官方是这么称呼的,思路就是遍历,然后将每个元素与它之前的 k 个元素中比较查看它们是否相等。

代码就略过了。

总结

以前断断续续也看过一些算法书,里面的窗口也是挺眼熟,这是在我的题解中第一次出现窗口这个字眼,其实抛开看似这么专业的称呼,我们就以实际例子(窗口就是一个框,滑动就是框去套,平移)去理解就非常好理解了。

所以还是实践出真知,很多理论都是实践出来的,很多模板,设计模式也都是总结抽象出来的。

参考

存在重复元素 II - 存在重复元素 II - 力扣(LeetCode) (leetcode-cn.com)

画解算法:219. 存在重复元素 II - 存在重复元素 II - 力扣(LeetCode) (leetcode-cn.com)