@@ -35,7 +35,55 @@ https://leetcode-cn.com/problems/contains-duplicate-iii/
3535
3636- 暂无
3737
38- ## 思路
38+ ## 暴力(超时)
39+
40+ ### 思路
41+
42+ 最简单的思路就是双层循环,找出所有的两两组合。然后逐个判断其是否满足 ` nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。 `
43+
44+ ### 代码
45+
46+ ``` python
47+ class Solution :
48+ def containsNearbyAlmostDuplicate (self , nums : List[int ], k : int , t : int ) -> bool :
49+ for i in range (len (nums)):
50+ for j in range (i + 1 , len (nums)):
51+ if abs (nums[i] - nums[j]) <= t and j - i <= k:
52+ return True
53+ return False
54+ ```
55+
56+ ** 复杂度分析**
57+
58+ - 时间复杂度:$O(N ^ 2)$
59+ - 空间复杂度:$O(1)$
60+
61+ ## 暴力 + 剪枝 (超时)
62+
63+ ### 思路
64+
65+ 上述的内存循环可以稍微优化一下, 之前我们从 i + 1 到 len(nums),实际上我们只需要 i + 1 到 min(len(nums), i + k + 1)。这样我们的 ` j - i <= k ` 也可以省略了。
66+
67+ ### 代码
68+
69+ ``` python
70+ class Solution :
71+ def containsNearbyAlmostDuplicate (self , nums : List[int ], k : int , t : int ) -> bool :
72+ for i in range (len (nums)):
73+ for j in range (i + 1 , min (len (nums), i + k + 1 )):
74+ if abs (nums[i] - nums[j]) <= t:
75+ return True
76+ return False
77+ ```
78+
79+ ** 复杂度分析**
80+
81+ - 时间复杂度:$O(N ^ 2)$
82+ - 空间复杂度:$O(1)$
83+
84+ ## 分桶 (通过)
85+
86+ ### 思路
3987
4088这道题是 [ 219. 存在重复元素 II] ( https://github.com/azl397985856/leetcode/blob/master/problems/219.contains-duplicate-ii.md ) 的进阶版。那道题的条件是 ` nums[i] == nums[j] ` , 而这道题则更加宽泛,是` nums [i] 和 nums [j] 的差的绝对值小于等于 t ` 。
4189
@@ -53,23 +101,36 @@ https://leetcode-cn.com/problems/contains-duplicate-iii/
53101
54102另外由于题目限定是索引差小于等于 k,因此我们可以固定一个窗口大小为 k 的滑动窗口,每次都仅处理窗口内的元素,这样可以保证桶内的数任意两个数都满足** 索引之差的绝对值小于等于 k** 。 因此我们需要清除哈希表中过期(不在窗口内)的信息。
55103
56- ## 关键点
104+ 具体算法:
105+
106+ - 我们将数据分到 M 个桶 中。
107+ - 每个数字 nums[ i] 都被我们分配到一个桶中
108+ - 分配的依据就是 nums[ i] // (t + 1)
109+ - 这样相邻桶内的数字最多相差` 2 * t + 1 `
110+ - 不相邻的桶一定不满足相差小于等于 t
111+ - 同一个桶内的数字最多相差` t `
112+
113+ 1 . 因此如果命中同一个桶内,那么直接返回 True
114+ 2 . 如果命中相邻桶,我们再判断一下是否满足 相差 <= t
115+ 3 . 否则返回 False
116+
117+ 需要注意的是,由于题目有索引相差 k 的要求,因此要维护一个大小为 k 的窗口,定期清除桶中` 过期 ` 的数字。
118+
119+ ### 关键点
57120
58121- 分桶排序思想的应用
59122
60- ## 代码
123+ ### 代码
61124
62- - 语言支持:Python3
125+ 我们使用哈希表来模拟桶,key 就是桶号,value 就是数字本身。
63126
64- Python3 Code :
127+ Python 3 :
65128
66129``` python
67-
68130class Solution :
69131 def containsNearbyAlmostDuplicate (self , nums : List[int ], k : int , t : int ) -> bool :
70132 bucket = dict ()
71- if t < 0 :
72- return False
133+ if t < 0 : return False
73134 for i in range (len (nums)):
74135 nth = nums[i] // (t + 1 )
75136 if nth in bucket:
@@ -79,11 +140,41 @@ class Solution:
79140 if nth + 1 in bucket and abs (nums[i] - bucket[nth + 1 ]) <= t:
80141 return True
81142 bucket[nth] = nums[i]
82- # 如果数组有相同的数会有影响么?答案是不会,因为如果有相同的数,我们直接就会在前面返回 true 了。
83- if i >= k:
84- bucket.pop(nums[i - k] // (t + 1 ))
143+ if i >= k: bucket.pop(nums[i - k] // (t + 1 ))
85144 return False
145+ ```
86146
147+ C++
148+
149+ ``` c++
150+ class Solution {
151+ public:
152+ bool containsNearbyAlmostDuplicate(vector<int >& nums, int k, int t) {
153+ if(t<0) return false;
154+ //t+1可能会溢出,所以要+ 1LL
155+ long long mod = t + 1LL;
156+ unordered_map<long long,long long> buck;
157+ for(int i=0;i<nums.size();i++)
158+ {
159+ long long nth = nums[ i] / mod;
160+ //可能nums[ i] 为负数,比如-4 / 5 以及 -4 / 5都等于0,所以负数要向下移动一位
161+ if(nums[ i] < 0) nth--;
162+ //这里要用find 不能直接[ ] ,因为可能本身存储的数字就为0
163+ if(buck.find(nth)!=buck.end())
164+ return true;
165+ else if(buck.find(nth-1)!=buck.end() && abs(nums[ i] - buck[ nth-1] ) <= t)
166+ return true;
167+ else if(buck.find(nth+1)!=buck.end() && abs(nums[ i] - buck[ nth+1] ) <= t)
168+ return true;
169+ buck[ nth] = nums[ i] ;
170+ if(i >= k)
171+ {
172+ buck.erase(nums[ i - k] / mod);
173+ }
174+ }
175+ return false;
176+ }
177+ };
87178```
88179
89180**复杂度分析**
0 commit comments