题目:

给你一个整数数组 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. 泰凌微TLSR825x智能照明解决方案开发之实例解析

    一 前记 前几天,看到了一个笑话,一个朋友在群里吼道,老婆送的皮带,用了半年之后,怎么里面掉出来一个电路板,这个是是啥? 笔者看了回复道,哥们,老婆不放心你啊. 在这个万物都可智能的时代,产品不加上智 ...

  2. offer收割机--js的隐式类型转换规则整理

    类型转换 文中的值类型等价于所说的基础类型,其范围是(boolean,string,number) 转换为基础类型 布尔值 undefined, null, false, NaN,'', 0 --&g ...

  3. StableSwarmUI:功能强大且易于使用的Stable Diffusion WebUI

    StableSwarmUI是一个模块化和可定制的Stable Diffusion WebUI,最近发布了0.6.1-Beta版本.这个开源项目,托管在GitHub上:https://github.co ...

  4. CSS(复合选择器、显示模式、背景属性)

    一.emmet语法 1.简介 Emmet语法的前身是Zen coding,它使用缩写,来提高html/css的编写速度, Vscode内部已经集成该语法. 快速生成HTML结构语法 快速生成CSS样式 ...

  5. 大模型应用开发:手把手教你部署并使用清华智谱GLM大模型

    部署一个自己的大模型,没事的时候玩两下,这可能是很多技术同学想做但又迟迟没下手的事情,没下手的原因很可能是成本太高,近万元的RTX3090显卡,想想都肉疼,又或者官方的部署说明过于简单,安装的时候总是 ...

  6. power quyer 批量合并同一文件夹下数据格式相同的Excel文件

    一.需求描述:现在有一批数据格式相同的Excel文件需要把里面的内容合并到同一个Excel的一个sheet里面 二.新建一个叫数据汇总的Excel文件-数据-新建查询-从文件-选择数据存放的文件夹-然 ...

  7. JNDI注入分析

    JNDI介绍 JNDI(Java Naming and Directory Interface,Java命名和目录接口)是为Java应用程序提供命名和目录访问服务的API,允许客户端通过名称发现和查找 ...

  8. 谈谈MyBatis持久层框架

    谈谈 MyBatis 源自官方文档:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作. ...

  9. Rust 实现日志记录功能

    目录 log 日志库标准 简单示例 使用方法 库的开发者 应用开发者 日志库开发者 使用 log4rs 添加依赖 配置文件 运行项目 参考文章 log 日志库标准 log 是 Rust 的日志门面库, ...

  10. SC的板子库~

    观前须知 Sugar_Cube的博客园主页 声明 本文所有内容遵循CC BY-NC-SA 4.0 Deed原则 本文包含了笔者常用的OI算法.数据结构的模板 不保证算法最优,但能通过相应的模板题(如果 ...