AlgoMooc
你已开通华为OD训练营权益,还差最后一步——完成入营激活(兑换课程 + 加飞书 + 登记服务群),即可解锁全部课程与专属服务。去激活 →
← OD 20 天课程

华为 OD 训练营 · 题解精讲

LC219. 存在重复元素II

LC219. 存在重复元素II

题目描述

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。 示例 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 提示: 1 <= nums.length <= 10^5 -109 <= nums[i] <= 10^9 0 <= k <= 10^5

题目解析

解题思路

题目要求判断数组中是否存在两个相同元素,且它们的索引差不超过 k。核心思路是用哈希表记录每个元素最近一次出现的索引,在遍历数组时,若当前元素已在哈希表中,则检查当前索引与之前索引的差值是否 ≤ k,若满足则直接返回 true;否则更新该元素的最新索引。遍历结束后未找到则返回 false

数据结构:哈希表(Python 字典),键为元素值,值为该元素最近一次出现的索引。

算法:一次线性扫描,利用哈希表进行快速查找。

关键步骤

1. 初始化:创建空字典 pos。 2. 遍历数组:使用 enumerate 同时获取索引 i 和元素值 v。 3. 检查重复

  • v 已在 pos 中,且 i - pos[v] <= k,则找到满足条件的索引对,返回 true
  • 否则,更新 pos[v] = i(无论是否满足条件,都要更新为最新索引,因为后续可能用更近的索引判断)。

4. 遍历结束:返回 false

示意图(以 nums=[1,2,3,1], k=3 为例):


i=0, v=1: pos={} → 未找到,更新 pos[1]=0
i=1, v=2: pos={1:0} → 未找到,更新 pos[2]=1
i=2, v=3: pos={1:0,2:1} → 未找到,更新 pos[3]=2
i=3, v=1: pos[1]=0, i-0=3 ≤ k=3 → 返回 true

复杂度分析

  • 时间复杂度:O(n),其中 n 为数组长度。只需一次遍历,哈希表查找和插入均为 O(1)。
  • 空间复杂度:O(min(n, k))。哈希表最多存储 min(n, k) 个元素(实际最坏情况存储所有不同元素,但题目保证 k 可能很大,因此最坏为 O(n))。

参考代码

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:

        # 使用哈希集合
        pos = {}

        # 如果想在 for 循环中同时获得列表的索引 i 和元素值 v
        # 可以使用枚举内置函数 enumerate()
        for i, v in enumerate(nums):
            # 1、如果发现当前这个元素 v 已经存在于哈希集合里面
            # 说明在此之前就已经访问到了一个元素,值为 v
            # 2、pos[v] 表示的是之前访问到的元素值所在的索引
            # 判断 i - pos[v] <= k
            if v in pos and i - pos[v] <= k:
                # 符合要求,就返回 True
                return True
            # 否则,把 v 和 i 存储到哈希集合里面
            pos[v] = i

        # 最终没有找到,返回 False
        return False