Leetcode 剑指 Offer II 057. 存在重复元素 III

2023-12-16 11:30

本文主要是介绍Leetcode 剑指 Offer II 057. 存在重复元素 III,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给你一个整数数组 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 * 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
  • 0 <= k <= 10^4
  • 0 <= t <= 2^31 - 1

题目思考

  1. 如何优化时间复杂度?

解决方案

思路
  • 分析题目, 一个很容易想到的思路就是暴力两重循环, 外层遍历每个数字作为起点, 内层从该起点向后遍历 k 个数字, 判断是否存在差值不超过 t 的数字对
  • 不过这种做法的时间复杂度达到了 O(NK), 很容易超时, 如何优化呢?
  • 上面的暴力法是通过两重循环的方式保证下标差有效, 然后再判断差值, 我们可以换个思路, 先保证差值有效, 然后再判断下标差
  • 由于题目要求差值不超过 t, 如果我们将数字映射到一个个桶中, 然后每个桶的大小是 t+1, 数字 x 对应的桶 id 就是 x/(t+1), 这样就只需要遍历相邻的三个桶即可
    • 举个例子: 对于某个数字 x, 假设其对应的桶 id 是 j, 那么只需要判断相邻的三个桶(j-1,j,j+1)即可, 因为其他桶的数字与 x 的差值一定超过 t (中间至少间隔了一个桶, 即 t+1)
  • 然后每个桶存储最新映射到该桶的数字的下标, 这样就很容易判断下标差是否超过 k 了
  • 最后我们还得再次确认对应数字对的差值是否真的不超过 t, 因为相邻桶的两个数字差值可能会超过 t, 例如数字对(x, x+t+1)
  • 另外注意, 我们在遍历某个下标 i 时, 总是可以将对应桶的值更新为它, 因为即使之前存在另一个下标 pi 也映射到这个桶, 那么当遍历后面的某个下标 j 时 (即pi<i<j), 只可能有两种情况:
    1. pi 和 j 的下标差不超过 k: 此时 pi 和 i 的下标差更不会超过 k, 所以 pi 和 i 本身就构成了有效的数字对 (在同一个桶内, 差值总是不超过 t), 遍历 i 时就可以直接返回 true
    2. pi 和 j 的下标差超过 k: pi 和 j 不能构成有效的数字对
  • 综合两种情况, pi 不会再被用到, 所以总是可以将桶的值更新为最新的下标 i
  • 下面代码中有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(N): 只需要遍历每个数字一遍
  • 空间复杂度 O(N): 额外桶映射字典, 最差情况每个数字对应独立的一个桶
代码
class Solution:def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:# 将数字离散化放到对应的桶中, 每个桶的大小是t+1, 数字x对应的桶id就是x/(t+1)# 这样对于某个数字x, 假设其对应的桶id是j, 那么只需要判断(j-1,j,j+1)三个桶即可, 因为其他桶的数字与x的差值一定超过tbuckets = {}for i, x in enumerate(nums):# 求出对应桶idid = x // (t + 1)for nid in (id - 1, id, id + 1):# 遍历相邻三个桶if nid in buckets and i - buckets[nid] <= k and abs(x - nums[buckets[nid]]) <= t:# 如果存在下标差不超过k, 且差值不超过t的数字对, 则有效# 注意这里不能省略差值判断, 因为相邻桶的两个数字差值可能会超过t, 例如数字对(x, x+t+1)return True# 在遍历某个下标 i 时, 总是可以将对应桶的值更新为它, 因为即使之前存在另一个下标 pi 也映射到这个桶, 那么当遍历后面的某个下标 j 时 (即`pi<i<j`), 只可能有两种情况:# 1. pi和j的下标差不超过k: 此时pi和i的下标差更不会超过k, 所以pi和i本身就构成了有效的数字对 (在同一个桶内, 差值总是不超过t), 遍历i时就可以直接返回true# 2. pi和j的下标差超过k: pi和j不能构成有效的数字对# 综合两种情况, pi不会再被用到, 所以总是可以将桶的值更新为最新的下标ibuckets[id] = ireturn False

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

这篇关于Leetcode 剑指 Offer II 057. 存在重复元素 III的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/500302

相关文章

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

Redis 多规则限流和防重复提交方案实现小结

《Redis多规则限流和防重复提交方案实现小结》本文主要介绍了Redis多规则限流和防重复提交方案实现小结,包括使用String结构和Zset结构来记录用户IP的访问次数,具有一定的参考价值,感兴趣... 目录一:使用 String 结构记录固定时间段内某用户 IP 访问某接口的次数二:使用 Zset 进行

Spring Boot 整合 ShedLock 处理定时任务重复执行的问题小结

《SpringBoot整合ShedLock处理定时任务重复执行的问题小结》ShedLock是解决分布式系统中定时任务重复执行问题的Java库,通过在数据库中加锁,确保只有一个节点在指定时间执行... 目录前言什么是 ShedLock?ShedLock 的工作原理:定时任务重复执行China编程的问题使用 Shed

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

Oracle数据库使用 listagg去重删除重复数据的方法汇总

《Oracle数据库使用listagg去重删除重复数据的方法汇总》文章介绍了在Oracle数据库中使用LISTAGG和XMLAGG函数进行字符串聚合并去重的方法,包括去重聚合、使用XML解析和CLO... 目录案例表第一种:使用wm_concat() + distinct去重聚合第二种:使用listagg,

MySQL中删除重复数据SQL的三种写法

《MySQL中删除重复数据SQL的三种写法》:本文主要介绍MySQL中删除重复数据SQL的三种写法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录方法一:使用 left join + 子查询删除重复数据(推荐)方法二:创建临时表(需分多步执行,逻辑清晰,但会

python 字典d[k]中key不存在的解决方案

《python字典d[k]中key不存在的解决方案》本文主要介绍了在Python中处理字典键不存在时获取默认值的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录defaultdict:处理找不到的键的一个选择特殊方法__missing__有时候为了方便起见,

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c