leetcode 220. Contains Duplicate III | 220. 存在重复元素 III (Treeset解法+分桶解法)
题目
https://leetcode.com/problems/contains-duplicate-iii/
题解
方法1:Treeset 解法,滑动窗口 & 二分
思路参考:https://leetcode-cn.com/problems/contains-duplicate-iii/solution/gong-shui-san-xie-yi-ti-shuang-jie-hua-d-dlnv/
用 Treeset 维护滑动窗口。Treeset 基于红黑树,插入和查找都有折半的效率。
import java.util.Arrays;
import java.util.TreeSet;class Solution {public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {TreeSet<Long> set = new TreeSet<>();for (int i = 0; i < nums.length; i++) {Long floor = set.floor((long) nums[i]); // 小于的里面的最大的if (floor != null && floor >= (long) nums[i] - t) return true;Long ceiling = set.ceiling((long) nums[i]); // 大于的里面的最小的if (ceiling != null && ceiling <= (long) nums[i] + t) return true;set.add((long) nums[i]);if (i - k >= 0) set.remove((long) nums[i - k]);}return false;}
}
方法2:分桶解法
参考:https://leetcode-cn.com/problems/contains-duplicate-iii/solution/c-li-yong-tong-fen-zu-xiang-xi-jie-shi-b-ofj6/
将 t+1 作为桶的模:
核心思路
我们从头开始遍历数组,对于当前下标i,有效的桶是下标为[i-k,i+k]的元素构造的桶,对于每一个i我们只需要看前面是否有无效的桶并删除即可,后面的元素我们没遍历到,自然也不会产生桶,所以 [i-k,i] 的桶是有效的,如果 nums[i-(k+1)] 产生的桶存在,我们要把其删除掉。因为 abs(i-(i-(k+1))) = abs(k+1) = k+1 > k。这是不在我们下标范围内的元素产生的桶,我们不需要判断是否满足条件,直接把这个桶删除了。
对于遍历到的元素 nums[i] 进行分桶,获取当前桶 ID,如果当前桶中已经有元素了,那么说明能找到符合条件的元素,直接返回true(因此,我们每个桶中最多只可能有一个元素,多了我们会直接返回结果)。如果当前桶没有元素,那么看看前相邻的桶有没有元素,如果有元素,那么进行做差比较,判断是否满足条件,满足则返回true。如果没有找到,那么把这个元素装入桶中,供别的元素判断。如果到最后都没有找到满足条件的元素,我们就返回false;
class Solution {public:long getID(long x, long t){//如果x元素大于等于零,直接分桶if(x>=0){return x / ( t + 1 );}else{//如果x元素小于零,偏移后再分桶return ( x + 1 )/( t + 1 ) - 1 ;}return 0;}bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {int n = nums.size();//我们用unordered_map来实现桶,其底层实现是一个哈希表.unordered_map<int,int> m;for(int i = 0 ; i < n; i++ ){//当前元素long x = nums[i];//给当前元素生成id,这里我们同一个id的桶内元素满足abs(nums[i] - nums[j]) <= tint id = getID(x,t);//前面的i-(k+1)是超出了范围的桶,我们把它提前删除,以免影响判断if( i-(k+1) >= 0 ){//把下标不满足我们判断范围的桶删除了m.erase(getID(nums[i-(k+1)],t));}//看看当前元素属于的桶中有没有元素if(m.find(id)!=m.end()){return true;}//看看前面相邻桶有没有符合条件的if(m.find(id - 1) != m.end() && abs(m[id-1]-x) <= t){return true;}//看看后面相邻桶有没有符合条件的if(m.find(id + 1) != m.end() && abs(m[id+1]-x) <= t){return true;}//分桶,把这个元素放入其属于的桶m[id] = x;}return false;}
};
Q&A
1、每个桶只存放一个元素,够用吗?
桶的解法相当凝练,不过有一点可以啰嗦两句。不知道有没有人疑惑,在比较id - 1和id + 1这两个相邻桶时,只比较了一个元素,这足够吗?哈希表的行为不是会用新元素覆盖旧元素,一个桶里有多个元素怎么办?
其实是覆盖根本不会发生…因为一旦要覆盖,就说明存在两个元素同属一个桶,直接返回true了。这就是题解说的“一个桶内至多只会有一个元素”——数组输入里当然可以有多个元素属于同一个桶,但是一旦出现一对,算法就结束了。
2、 i-(k+1) 是超出了范围的桶,我们把它提前删除的话,会不会误伤有效范围内的桶?
误伤根本不会发生。假设有一个序列是 5, 7, 9, 1_a, [3, 5, 1_b, 1_c]
的话(括号内是当前窗口),我们会担心删除 1_a 的时候会误伤 1_b 的桶。而实际上,不会存在这种误伤问题。因为只有相同桶里的元素才能被误伤,而既然有两个元素属于同一个桶,算法早就应该结束了。
leetcode 220. Contains Duplicate III | 220. 存在重复元素 III (Treeset解法+分桶解法)相关推荐
- python【力扣LeetCode算法题库】220-存在重复元素 III
给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. 示例 1: 输入: ...
- 【桶】220.存在重复元素 III 【LeetCode】
220.存在重复元素 III [LeetCode] 给你一个整数数组 nums 和两个整数 k 和 t.请你判断是否存在 两个不同下标i和j,使得 abs(nums[i] - nums[j]) < ...
- LeetCode—220. 存在重复元素 III
220. 存在重复元素 III 题目描述: 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) < ...
- 7-1 有重复元素的全排列 (10 分)
7-1 有重复元素的全排列 (10 分) 计算给定的n个数有多少种排列方式,即求全排列(可能出现重复的元素) 输入格式: 第一行输入数字的数量n(n>2),第二行给出每一个数字. 输出格式: 一 ...
- python【力扣LeetCode算法题库】217-存在重复元素
给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3,1] 输出: true ...
- 7-6 数据结构实验之链表七:单链表中重复元素的删除 (20 分)
按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删除(值相同的元素只保留最后输入的一个). 输入格式: 第一行输入元素个数 n (1 <= n <= 15): 第二行 ...
- LeetCode 220. 存在重复元素 III(lower_bound)
文章目录 1. 题目 2. 解题 1. 题目 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间 ...
- Leetcode 220. 存在重复元素 III 解题思路及C++实现
解题思路: 使用set集合来实现滑动窗口k,对窗口内的数进行比较,得到结果. 使用两个指针i.j,来确定窗口位置,i走在前面,j在后面.因为数组内这两个数的差值绝对值限制为:| x - nums[i] ...
- leetcode 220. 存在重复元素 III(排序)
给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) ...
最新文章
- TensorFlow、PyTorch之后,“国产”AI框架还有没有机会?
- Exception testing
- 天涯社区服务器位置,天涯到底怎么了,哪份帖子都打不开,是服务器的问题吗...
- 五、jvm垃圾回收3(几种垃圾收集器)
- Flask之threading.loacl方法
- python简短语法_写出优雅简洁的 python 语法(二)函数传参
- C++ - C++ signal的使用
- d. powerful ksenia_DEBON D.D |这才是每个女人应该拥有的
- AD19无法生成PCB_PCB制造拥抱AI
- 一文快速了解 Java 9 - 16 新特性,网友:卷不动了?
- Chrome安装Octotree插件
- java 毕业论文_Java程序设计毕业论文.doc
- 软件开发的版本控制管理
- excel各种填充的总结
- 全桥驱动IR系列参考设计及问题指南
- linux之文件压缩解压
- android音乐播放器开发 SweetMusicPlayer 播放本地音乐
- 包装类型与引用类型的使用场景
- 导入Excel文件的方法
- 2023必须收藏的16个Python接单平台,做私活爽歪歪!附100个爬虫源码,拿去吧你