当前位置: 首页 > news >正文

LeetCode 220 存在重复元素 III 题解

LeetCode 220 存在重复元素 III 题解

题目描述

给定一个整数数组 nums 和两个整数 k 和 t,请判断数组中是否存在两个不同的索引 i 和 j,使得:

  1. abs(nums[i] - nums[j]) <= t
  2. abs(i - j) <= k

方法思路:桶排序 + 滑动窗口

核心思想

  1. 桶排序思想:将数值范围划分为大小为t+1的桶

    • 每个元素根据值分配到对应的桶(编号 = 值 // (t+1))

    • 同一桶内的元素自然满足差值条件

    • 相邻桶的元素需要额外验证差值,
      相邻桶要验证额外差值的具体原因和实现逻辑:

      1.1 桶的划分方式 每个桶的宽度是 t + 1 (w = t + 1),桶编号通过 数值 // w 计算得到。这种划分方式导致:

        - 同一桶内元素的差值 一定 ≤ t (自动满足条件)- 相邻桶中元素 可能满足差值 ≤ t
      

      1.2. 边界情况示例 假设 t=3(w=4),数值分布:

        - 桶0:[0-3]- 桶1:[4-7]- 桶-1:[-4--1]当出现:- 数值3(桶0)和4(桶1) → 差1 ≤ 3- 数值-1(桶-1)和0(桶0) → 差1 ≤ 3
      

      1.3 必须显式验证的原因 相邻桶中的元素不一定满足差值条件(比如桶0的3和桶1的7差4>3),因此需要通过 abs(nums[i] - bucket_value) < w 的二次验证,确保实际差值 ≤ t
      1.4. 算法完整性 这种设计保证三种可能性都被覆盖:

        - ✅ 同桶元素 → 直接返回- ✅ 左邻桶元素 → 验证后返回- ✅ 右邻桶元素 → 验证后返回
      
  2. 滑动窗口:维护大小为k的窗口

    • 使用字典记录当前窗口内的元素
    • 当窗口超过k个元素时,删除最早进入的元素

算法步骤

  1. 处理非法输入(t < 0)
  2. 初始化桶字典和桶宽度w = t + 1
  3. 遍历数组元素:
    • 计算当前元素的桶编号
    • 检查当前桶和相邻桶是否满足条件
    • 维护滑动窗口大小(删除过期元素)

复杂度分析

  • 时间复杂度:O(n),每个元素处理时间为O(1)
  • 空间复杂度:O(min(n,k)),滑动窗口最多保存k个元素

关键点说明

  1. 桶宽度选择t+1的宽度保证了:

    • 同一桶内元素差≤t
    • 相邻桶元素需要显式验证差值
  2. 滑动窗口维护

    if i >= k:expired_bucket = nums[i - k] // wdel bucket[expired_bucket]
    

这保证了任何时候桶中只包含最近k个元素

  1. 负数处理 :Python的整数除法是向下取整,例如:
    • -3 // 4 = -1 (而正数3//4=0)
    • 这确保了相邻负数的正确分桶

示例输入

nums = [1, 5, 9, 1, 5, 9]
k = 2
t = 3

输出应为False,因为虽然存在相同元素,但索引差超过k的限制

LeetCode 220 存在重复元素 III

https://leetcode.cn/problems/7WqeDu/

解法:桶排序 + 滑动窗口 时间复杂度O(n) 空间复杂度O(min(n,k))

# LeetCode 220 存在重复元素 III
# https://leetcode.cn/problems/7WqeDu/
# 解法:桶排序 + 滑动窗口 时间复杂度O(n) 空间复杂度O(min(n,k))from typing import Listclass Solution:def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:"""判断数组中是否存在满足以下条件的两个不同索引i,j:1. abs(nums[i] - nums[j]) <= t2. abs(i - j) <= k参数:nums: 输入数组k: 索引最大差值(滑动窗口大小)t: 数值最大差值返回:bool: 是否存在满足条件的元素对"""if t < 0:  # 处理非法输入,t不能为负数return Falsen = len(nums)bucket = {}  # 用字典维护桶,键为桶编号,值为桶中元素值w = t + 1    # 桶的宽度(避免t=0时除零错误)for i in range(n):# 计算当前元素所属的桶编号bucket_id = nums[i] // w  # 整数除法自动向下取整# 检查当前桶是否已有元素(保证数值差<=t)if bucket_id in bucket:return True# 检查左侧相邻桶(需要额外验证数值差)if (bucket_id - 1) in bucket and abs(nums[i] - bucket[bucket_id - 1]) < w:return True# 检查右侧相邻桶(需要额外验证数值差)if (bucket_id + 1) in bucket and abs(nums[i] - bucket[bucket_id + 1]) < w:return True# 将当前元素加入桶bucket[bucket_id] = nums[i]# 维护滑动窗口,当i>=k时删除最早进入桶的元素if i >= k:expired_bucket = nums[i - k] // wdel bucket[expired_bucket]return Falseif __name__ == "__main__":# 测试用例(题目示例)nums = [1, 5, 9, 1, 5, 9]k = 2t = 3print(Solution().containsNearbyAlmostDuplicate(nums, k, t))  # 预期输出:False

相关文章:

  • 高铁座位指示灯系统技术深度解析:从物联网到智慧出行的实践路径
  • [论文阅读]Deep Cross Network for Ad Click Predictions
  • 机器学习例题——预测facebook签到位置(K近邻算法)和葡萄酒质量预测(线性回归)
  • 多模态训练与微调
  • TypeScript简介
  • MPay码支付系统第四方聚合收款码多款支付插件个人免签支付源码TP8框架全开源
  • MD2card + Deepseek 王炸组合 一键制作小红书知识卡片
  • Qwen3与Deepseek R1对比(截止20250506)
  • CentOS 7 安装指定版本 Docker 及镜像加速/配置优化攻略
  • 计算机视觉与深度学习 | 基于数字图像处理的裂缝检测与识别系统(matlab代码)
  • SiC 材料及器件在高频大功率领域的应用现状
  • MCP服务发展现状的有趣发现
  • 【每天一个知识点】使用 apriori() 函数获取频繁项集
  • 论广告系统对存算分离架构的应用
  • 代码随想录算法训练营第60期第二十八天打卡
  • 1ms城市算网稳步启航,引领数字领域的“1小时经济圈”效应
  • C++复习
  • 老牌即时通讯应用Skype被关闭,卒年22岁!
  • 2024 ICPC武汉邀请赛暨湖北省赛 题解
  • [特殊字符]【深度解析】Transformer革命:《Attention Is All You Need》完全解读
  • 特朗普称美军舰商船应免费通行苏伊士运河,外交部:反对任何霸凌言行
  • 世界人形机器人运动会将在北京“双奥场馆”举行
  • 打造多元文旅消费场景,第四届长三角城市戏剧节启幕
  • “子宫内膜异位症”相关论文男性患者样本超六成?福建省人民医院展开调查
  • 五一档观众最满意《水饺皇后》
  • 实探北京楼市:“好房子”卖点十足,二手房持续回稳