题目

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解法+分桶解法)相关推荐

  1. python【力扣LeetCode算法题库】220-存在重复元素 III

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

  2. 【桶】220.存在重复元素 III 【LeetCode】

    220.存在重复元素 III [LeetCode] 给你一个整数数组 nums 和两个整数 k 和 t.请你判断是否存在 两个不同下标i和j,使得 abs(nums[i] - nums[j]) < ...

  3. LeetCode—220. 存在重复元素 III

    220. 存在重复元素 III 题目描述: 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) < ...

  4. 7-1 有重复元素的全排列 (10 分)

    7-1 有重复元素的全排列 (10 分) 计算给定的n个数有多少种排列方式,即求全排列(可能出现重复的元素) 输入格式: 第一行输入数字的数量n(n>2),第二行给出每一个数字. 输出格式: 一 ...

  5. python【力扣LeetCode算法题库】217-存在重复元素

    给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3,1] 输出: true ...

  6. 7-6 数据结构实验之链表七:单链表中重复元素的删除 (20 分)

    按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删除(值相同的元素只保留最后输入的一个). 输入格式: 第一行输入元素个数 n (1 <= n <= 15): 第二行 ...

  7. LeetCode 220. 存在重复元素 III(lower_bound)

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

  8. Leetcode 220. 存在重复元素 III 解题思路及C++实现

    解题思路: 使用set集合来实现滑动窗口k,对窗口内的数进行比较,得到结果. 使用两个指针i.j,来确定窗口位置,i走在前面,j在后面.因为数组内这两个数的差值绝对值限制为:| x - nums[i] ...

  9. leetcode 220. 存在重复元素 III(排序)

    给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) ...

最新文章

  1. TensorFlow、PyTorch之后,“国产”AI框架还有没有机会?
  2. Exception testing
  3. 天涯社区服务器位置,天涯到底怎么了,哪份帖子都打不开,是服务器的问题吗...
  4. 五、jvm垃圾回收3(几种垃圾收集器)
  5. Flask之threading.loacl方法
  6. python简短语法_写出优雅简洁的 python 语法(二)函数传参
  7. C++ - C++ signal的使用
  8. d. powerful ksenia_DEBON D.D |这才是每个女人应该拥有的
  9. AD19无法生成PCB_PCB制造拥抱AI
  10. 一文快速了解 Java 9 - 16 新特性,网友:卷不动了?
  11. Chrome安装Octotree插件
  12. java 毕业论文_Java程序设计毕业论文.doc
  13. 软件开发的版本控制管理
  14. excel各种填充的总结
  15. 全桥驱动IR系列参考设计及问题指南
  16. linux之文件压缩解压
  17. android音乐播放器开发 SweetMusicPlayer 播放本地音乐
  18. 包装类型与引用类型的使用场景
  19. 导入Excel文件的方法
  20. 2023必须收藏的16个Python接单平台,做私活爽歪歪!附100个爬虫源码,拿去吧你

热门文章

  1. 牛客 - 减成一(差分数组)
  2. POJ - 3250 Bad Hair Day(单调队列/单调栈)
  3. java中spring的级别_java – 在简单的示例项目中更改Spring框架日志级别?
  4. HDU4622(后缀自动机)
  5. delphi7下安装TMS component
  6. linux下动态链接库(.so)的显式调用和隐式调用
  7. 透过汇编另眼看世界之DLL导出函数调用
  8. 那些做了十年的老开发都去哪了?
  9. 突发!Redis之父退出:不在维护Redis项目
  10. 惊!空 struct 地址竟然不相等