Skip to content

Commit 21bc088

Browse files
author
lucifer
committed
fix: 加入暴力解
1 parent 6e26c56 commit 21bc088

File tree

1 file changed

+102
-11
lines changed

1 file changed

+102
-11
lines changed

problems/220.contains-duplicate-iii.md

Lines changed: 102 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
68130
class 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

Comments
 (0)