题目:

给你一个整数数组 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=2147483647
  • 0 <= k <= 104
  • 0 <= t <= 231 - 1

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/contains-duplicate-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

题解参考@【liweiwei1419】

滑动窗口&红黑树(TreeSet):

题目中的两个要求: 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t,同时又满足abs(i - j) <= k。 

1.对于两个位置的下标的范围,可以维护一个长度为 k + 1的滑动窗口(解释:[1,3,5,3,4,6] k =3,滑动窗口的长度可以为4,因为在四个连续的数的下标差一定会小于等于3)。但是滑动窗口中的元素可能为k个,也可能为k+1个,如果先插入新元素则是k+1个,如果是先删除最左端的元素,则是k个。

2.对于两个位置所对应的数字差范围:abs(nums[i] - nums[j]) <= t,可以转换为:-t <= nums[i] - nums[j] <= t,把nums[i]看做新遍历到的元素,nums[j]看做是在滑动窗口里面的元素,将上述不等式可以转换为:

  • 条件1:nums[j] >= nums[i] - t;
  • 条件2:nums[j] <= nums[i] + t;

条件2的nums[i] + t的值固定,为了让条件2有更多的值成立,条件1找到得到nums[j]需要尽可能的小才行,于是就等价于找大于等于nums[i] - t的最小值,等价于找到nums[i] - t的最小上界。java中的ceiling(key)函数提供了这样的功能:返回大于等于key的最小元素,如果不存在,返回空。

为什么使用二分搜索树】解释来自【作者:liweiwei1419】
理由 1:由于维护的是固定长度的一系列数,除了最开始的几个数添加进数据结构以外。

当程序看到下标为 k + 1的元素的时候,就需要移除下标为 00 的元素;
当程序看到下标为 k + 2的元素的时候,就需要移除下标为 11 的元素。
频繁的删除和添加元素,符合条件的数据结构是「查找表」,「查找表」的两种实现分别是「哈希表」和「二分搜索树(红黑树)」。

理由 2:根据上面的分析,我们需要找到 nums[i] - t 的最小上界,「哈希表」是不维护元素顺序性的,而「二分搜索树」恰好维护了顺序性,是当前场景下合适的数据结构。且哈希表无法很好的支持范围查询。

注意:

int的溢出问题:例如nums= [-2147483640, -2147483641],k = 1, t = 100,nums[i] - t = -21474836740就会超过int 的最小值范围,故用long 类型来存储。

java代码:

 1 class Solution {
2 public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
3 TreeSet<Long> set = new TreeSet<>();
4 for(int i = 0; i < nums.length; i++){
5 //查找大于等于nums[i]-t的最小值
6 Long ceiling = set.ceiling((long)nums[i] - (long)valueDiff);
7 if(ceiling != null && ceiling <= ((long)nums[i] + (long)valueDiff)){
8 return true;
9 }
10 set.add((long)nums[i]);
11 //限制滑动窗口的大小
12 if(set.size() == indexDiff + 1){
13 set.remove((long)nums[i - indexDiff]);
14 }
15 }
16 return false;
17 }
18 }

 小知识:

1.java集合中存在以下两种方法:

floor(E e) 方法返回在这个集合中小于或者等于给定元素的最大元素,如果不存在这样的元素,返回null。

ceiling(E e) 方法返回在这个集合中大于或者等于给定元素的最小元素,如果不存在这样的元素,返回null。

2.TreeSet 是一个有序集合,它的作用是提供有序的Set集合。其继承于 AbstractSet 类TreeSet 实现了 NavigableSet 接口,意味着它支持一系列的导航方法。比如查找指定目标最匹配项。

TreeSet 是通过 TreeMap 实现的一个有序的、不可重复的集合,底层维护的是红黑树结构。当TreeSet的泛型对象不是java的基本类型的包装类时,对象需要实现接口Comparable并重写此接口中的compareTo()方法。 TreeSet 实现了 Serializable 接口,所以它支持序列化。

力扣220(java)-存在重复元素 III(困难)的更多相关文章

  1. Java实现 LeetCode 220 存在重复元素 III(三)

    220. 存在重复元素 III 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最 ...

  2. Leetcode 220.存在重复元素III

    存在重复元素III 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. ...

  3. 【每日算法】存在重复元素 III

    题目描述 这是 LeetCode 上的 220. 存在重复元素 III, 难度为 [中等] 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 ab ...

  4. [LeetCode] 220. Contains Duplicate III 包含重复元素 III

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

  5. 力扣——remove element(删除元素) python实现

    题目描述: 中文: 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) ...

  6. 力扣题目汇总(重复N次元素,反转字符串,斐波那契数)

    重复 N 次的元素 1.题目描述 在大小为 2N 的数组 A 中有 N+1 个不同的元素,其中有一个元素重复了 N 次. 返回重复了 N 次的那个元素. 示例 1: 输入:[1,2,3,3] 输出:3 ...

  7. [LeetCode]220. 存在重复元素 III

    题目链接:https://leetcode-cn.com/problems/contains-duplicate-iii/ 题目描述: 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使 ...

  8. 220. 存在重复元素 III

    题目: 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. 示例 1: ...

  9. 力扣Leetcode 3. 无重复字符的最长子串

    无重复字符的最长子串 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串 ...

  10. [Swift]LeetCode220. 存在重复元素 III | Contains Duplicate III

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

随机推荐

  1. find第二天

    find第二天 1.找出/tmp目录下,属主不是root,且文件名不以f开头的文件 find /tmp ! -user root -a ! -name 'f*' 或者 find /tmp ! -use ...

  2. 3DCAT荣获2021金陀螺“年度XR行业技术创新奖”“年度优秀VR行业应用奖”两项大奖

    作为年度行业影响力大奖,第六届金陀螺颁奖典礼与2021未来商业生态链接大会(简称"FBEC2021")同期举办.金陀螺奖金陀螺奖旨在对优质作品/项目及优秀企业做出嘉奖,鼓励创业者. ...

  3. 使用Go语言开发一个短链接服务:五、添加和获取短链接

    章节  使用Go语言开发一个短链接服务:一.基本原理  使用Go语言开发一个短链接服务:二.架构设计  使用Go语言开发一个短链接服务:三.项目目录结构设计  使用Go语言开发一个短链接服务:四.生成 ...

  4. C# OpenCvSharp+ 微信二维码引擎实现二维码识别

    微信开源了其二维码的解码功能,并贡献给 OpenCV 社区.其开源的 wechat_qrcode 项目被收录到 OpenCV contrib 项目中.从 OpenCV 4.5.2 版本开始,就可以直接 ...

  5. 痞子衡嵌入式:给i.MXRT1xxx系列GPIO提早供电会影响DCDC_PSWITCH上电时序导致内部DCDC启动失败

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是给i.MXRT1xxx系列GPIO提早供电会影响DCDC_PSWITCH上电时序导致内部DCDC启动失败. 最近有一个 RW612 产品 ...

  6. KingbaseES V8R6运维案例之---数据库resetwal后启动失败

    KingbaseES V8R6运维案例之---数据库resetwal后启动失败 案例说明: KingbaseES V8R6集群触发failover切换后,原主库自动recovery失败,现在需要将原主 ...

  7. KingbaseES V8R6 数据库运维案例之 -- root用户securecmd连接'Permission denied'错误

    案例分析: 在KingbaseES V8R6数据库在不支持ssh连接的系统环境,可以通过securecmdd服务建立主机之间的通讯,默认securecmdd服务建立用户之间的互信,通过publicke ...

  8. linux关闭主板警告声,蜂鸣声,滴滴声,pc扬声器。

    启动时,BIOS 通常会在开机自检期间发出蜂鸣声.较新的主板型号省略了开机自检蜂鸣声,以便快速启动进入操作系统.BIOS 通常允许切换开机自检蜂鸣声,但无法将 PC 扬声器配置为完全关闭.一旦系统启动 ...

  9. #dp,二项式反演,容斥#CF285E Positions in Permutations

    题目 问有多少个长度为 \(n\) 的排列 \(P\) 满足 \(|P_i-i|=1\) 的 \(i\) 的个数恰好为 \(k\) 个 分析 设 \(dp_{i,j,k}\) 表示前 \(i\) 个数 ...

  10. 如何通过OpenHarmony系统中集成的ffmpeg库和NAPI机制,实现更多的多媒体功能?

    简介 OpenAtom OpenHarmony(以下简称"OpenHarmony")作为"开源"世界的"连接器",不断为智能社会的发展提供源 ...