Skip to content

Commit 9ec1a5b

Browse files
committed
更新题解列表
1 parent bb9e5ea commit 9ec1a5b

9 files changed

+322
-69
lines changed

Solutions/0015. 三数之和.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
直接三重遍历查找 $a$、$b$、$c$ 的时间复杂度是:$O(n^3)$。我们可以通过一些操作来降低复杂度。
3838

39-
先将数组进行排序,以保证按顺序查找 $a$、$b$、$c$ 时,元素值为升序,从而保证所找到的三个元素是不重复的。同时也方便下一步使用双指针减少一重遍历。时间复杂度为:$O(nlogn)$。
39+
先将数组进行排序,以保证按顺序查找 $a$、$b$、$c$ 时,元素值为升序,从而保证所找到的三个元素是不重复的。同时也方便下一步使用双指针减少一重遍历。时间复杂度为:$O(n \times \log n)$。
4040

4141
第一重循环遍历 $a$,对于每个 $a$ 元素,从 $a$ 元素的下一个位置开始,使用对撞指针 $left$,$right$。$left$ 指向 $a$ 元素的下一个位置,$right$ 指向末尾位置。先将 $left$ 右移、$right$ 左移去除重复元素,再进行下边的判断。
4242

Solutions/0018. 四数之和.md

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,51 @@
55

66
## 题目大意
77

8-
给定一个整数数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a、b、c、d,使得 a + b + c + d = target。要求找出所有满足条件且不重复的四元组
8+
**描述**给定一个整数数组 $nums$ 和一个目标值 $target$
99

10-
## 解题思路
10+
**要求**:找出所有满足以下条件切不重复的四元组。
1111

12-
[0015. 三数之和](https://leetcode.cn/problems/3sum/) 解法类似。
12+
1. $0 \le a, b, c, d < n$。
13+
2. $a$、$b$、$c$ 和 $d$ 互不相同。
14+
3. $nums[a] + nums[b] + nums[c] + nums[d] == target$。
1315

14-
直接三重遍历查找 a、b、c、d 的时间复杂度是:$O(n^4)$。我们可以通过一些操作来降低复杂度。
16+
**说明**
1517

16-
先将数组进行排序,以保证按顺序查找 a、b、c、d 时,元素值为升序,从而保证所找到的四个元素是不重复的。同时也方便下一步使用双指针减少一重遍历。时间复杂度为:$O(nlogn)$
18+
- $1 \le nums.length \le 200$。
19+
- $-10^9 \le nums[i] \le 10^9$。
20+
- $-10^9 \le target \le 10^9$。
1721

18-
两重循环遍历元素 a、b,对于每个 a 元素,从 a 元素的下一个位置开始遍历元素 b。对于元素 a、b,使用双指针 left,right 来查找 c、d。left 指向 b 元素的下一个位置,right 指向末尾位置。先将 left 右移、right 左移去除重复元素,再进行下边的判断。
22+
**示例**
1923

20-
- `nums[a] + nums[b] + nums[left] + nums[right] = target`,则得到一个解,将其加入答案数组中,并继续将 left 右移,right 左移;
24+
- 示例 1:
2125

22-
-`nums[a] + nums[b] + nums[left] + nums[right] > target`,说明 nums[right] 值太大,将 right 向左移;
23-
-`nums[a] + nums[b] + nums[left] + nums[right] < target`,说明 nums[left] 值太小,将 left 右移。
26+
```python
27+
输入:nums = [1,0,-1,0,-2,2], target = 0
28+
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
29+
```
2430

25-
## 代码
31+
- 示例 2:
32+
33+
```python
34+
输入:nums = [2,2,2,2,2], target = 8
35+
输出:[[2,2,2,2]]
36+
```
37+
38+
## 解题思路
39+
40+
### 思路 1:排序 + 双指针
41+
42+
[0015. 三数之和](https://leetcode.cn/problems/3sum/) 解法类似。
43+
44+
直接三重遍历查找 $a$、$b$、$c$、$d$ 的时间复杂度是:$O(n^4)$。我们可以通过一些操作来降低复杂度。
45+
46+
1. 先将数组进行排序,以保证按顺序查找 $a$、$b$、$c$、$d$ 时,元素值为升序,从而保证所找到的四个元素是不重复的。同时也方便下一步使用双指针减少一重遍历。这一步的时间复杂度为:$O(n \times \log n)$。
47+
2. 两重循环遍历元素 $a$、$b$,对于每个 $a$ 元素,从 $a$ 元素的下一个位置开始遍历元素 $b$。对于元素 $a$、$b$,使用双指针 $left$,$right$ 来查找 $c$、$d$。$left$ 指向 $b$ 元素的下一个位置,$right$ 指向末尾位置。先将 $left$ 右移、$right$ 左移去除重复元素,再进行下边的判断。
48+
1. 如果 $nums[a] + nums[b] + nums[left] + nums[right] == target$,则得到一个解,将其加入答案数组中,并继续将 $left$ 右移,$right$ 左移;
49+
2. 如果 $nums[a] + nums[b] + nums[left] + nums[right] > target$,说明 $nums[right]$ 值太大,将 $right$ 向左移;
50+
3. 如果 $nums[a] + nums[b] + nums[left] + nums[right] < target$,说明 $nums[left]$ 值太小,将 $left$ 右移。
51+
52+
### 思路 1:代码
2653

2754
```python
2855
class Solution:
@@ -55,3 +82,8 @@ class Solution:
5582
return ans
5683
```
5784

85+
### 思路 1:复杂度分析
86+
87+
- **时间复杂度**:$O(n^3)$,其中 $n$ 为数组中元素个数。
88+
- **空间复杂度**:$O(\log n)$,排序额外使用空间为 $\log n$。
89+

Solutions/0350. 两个数组的交集 II.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
## 题目大意
77

8-
**描述**:给定两个数组 `nums1``nums2`
8+
**描述**:给定两个数组 $nums1$$nums2$
99

1010
**要求**:返回两个数组的交集。可以不考虑输出结果的顺序。
1111

Solutions/0383. 赎金信.md

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,47 @@
55

66
## 题目大意
77

8-
为了不在赎金信中暴露字迹,从杂志上搜索各个需要的字母,组成单词来表达意思。
8+
**描述**为了不在赎金信中暴露字迹,从杂志上搜索各个需要的字母,组成单词来表达意思。
99

10-
给定一个赎金信字符串 `ransomNote` 和一个杂志字符串 `magazine`
10+
给定一个赎金信字符串 $ransomNote$ 和一个杂志字符串 $magazine$
1111

12-
要求:判断 `ransomNote` 能不能由 `magazines` 里面的字符构成。如果可以构成,返回 `True`;否则返回 `False`
12+
**要求**:判断 $ransomNote$ 能不能由 $magazines$ 里面的字符构成。如果可以构成,返回 `True`;否则返回 `False`
1313

14-
注意:`magazine` 中的每个字符只能在 `ransomNote` 中使用一次。
14+
**说明**
15+
16+
- $magazine$ 中的每个字符只能在 $ransomNote$ 中使用一次。
17+
- $1 \le ransomNote.length, magazine.length \le 10^5$。
18+
- $ransomNote$ 和 $magazine$ 由小写英文字母组成。
19+
20+
**示例**
21+
22+
- 示例 1:
23+
24+
```python
25+
输入:ransomNote = "a", magazine = "b"
26+
输出:False
27+
```
28+
29+
- 示例 2:
30+
31+
```python
32+
输入:ransomNote = "aa", magazine = "ab"
33+
输出:False
34+
```
1535

1636
## 解题思路
1737

18-
暴力做法是双重循环遍历字符串 `ransomNote``magazine`。我们可以用哈希表来减少算法的时间复杂度。具体做法如下:
38+
### 思路 1:哈希表
1939

20-
- 先用哈希表存储 `magazine` 中各个字符的个数(哈希表可用字典或数组实现)。
21-
- 再遍历字符串 `ransomNote` 中每个字符,对于每个字符:
22-
- 如果在哈希表中个数为 `0`,直接返回 `False`
23-
- 如果在哈希表中个数不为 `0`,将其个数减 1。
24-
- 遍历到最后,则说明 `ransomNote` 能由 `magazines` 里面的字符构成。返回 `True`
40+
暴力做法是双重循环遍历字符串 $ransomNote$ 和 $magazines$。我们可以用哈希表来减少算法的时间复杂度。具体做法如下:
2541

26-
## 代码
42+
- 先用哈希表存储 $magazines$ 中各个字符的个数(哈希表可用字典或数组实现)。
43+
- 再遍历字符串 $ransomNote$ 中每个字符,对于每个字符:
44+
- 如果在哈希表中个数为 $0$,直接返回 `False`
45+
- 如果在哈希表中个数不为 $0$,将其个数减 $1$。
46+
- 遍历到最后,则说明 $ransomNote$ 能由 $magazines$ 里面的字符构成。返回 `True`
47+
48+
### 思路 1:代码
2749

2850
```python
2951
class Solution:
@@ -44,3 +66,8 @@ class Solution:
4466
return True
4567
```
4668

69+
### 思路 1:复杂度分析
70+
71+
- **时间复杂度**:$O(m + n)$,其中 $m$ 是字符串 $ransomNote$ 的长度,$n$ 是字符串 $magazines$ 的长度。
72+
- **空间复杂度**:$O(|S|)$,其中 $S$ 是字符集,本题中 $|S| = 26$。
73+

Solutions/0399. 除法求值.md

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,66 @@
55

66
## 题目大意
77

8-
给定一个变量对数组 `equations` 和一个实数数组 `values` 作为已知条件,其中 `equations[i] = [Ai, Bi]``values[i]` 共同表示 `Ai / Bi = values[i]`。每个 `Ai``Bi` 是一个表示单个变量的字符串。
8+
**描述**给定一个变量对数组 $equations$ 和一个实数数组 $values$ 作为已知条件,其中 $equations[i] = [Ai, Bi]$$values[i]$ 共同表示 `Ai / Bi = values[i]`。每个 $Ai$$Bi$ 是一个表示单个变量的字符串。
99

10-
再给定一个表示多个问题的数组 `queries`,其中 `queries[j] = [Cj, Dj]` 表示第 `j` 个问题,要求:根据已知条件找出 `Cj / Dj = ?` 的结果作为答案。返回所有问题的答案。如果某个答案无法确定,则用 `-1.0` 代替,如果问题中出现了给定的已知条件中没有出现的表示变量的字符串,则也用 `-1.0` 代替这个答案。
10+
再给定一个表示多个问题的数组 $queries$,其中 $queries[j] = [Cj, Dj]$ 表示第 $j$ 个问题,要求:根据已知条件找出 `Cj / Dj = ?` 的结果作为答案。
11+
12+
**要求**:返回所有问题的答案。如果某个答案无法确定,则用 $-1.0$ 代替,如果问题中出现了给定的已知条件中没有出现的表示变量的字符串,则也用 $-1.0$ 代替这个答案。
13+
14+
**说明**
15+
16+
- 未在等式列表中出现的变量是未定义的,因此无法确定它们的答案。
17+
- $1 \le equations.length \le 20$。
18+
- $equations[i].length == 2$。
19+
- $1 \le Ai.length, Bi.length \le 5$。
20+
- $values.length == equations.length$。
21+
- $0.0 < values[i] \le 20.0$。
22+
- $1 \le queries.length \le 20$。
23+
- $queries[i].length == 2$。
24+
- $1 \le Cj.length, Dj.length \le 5$。
25+
- $Ai, Bi, Cj, Dj$ 由小写英文字母与数字组成。
26+
27+
**示例**
28+
29+
- 示例 1:
30+
31+
```python
32+
输入:equations = [["a","b"],["b","c"]], values = [2.0,3.0], queries = [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]]
33+
输出:[6.00000,0.50000,-1.00000,1.00000,-1.00000]
34+
解释:
35+
条件:a / b = 2.0, b / c = 3.0
36+
问题:a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
37+
结果:[6.0, 0.5, -1.0, 1.0, -1.0 ]
38+
注意:x 是未定义的 => -1.0
39+
```
40+
41+
- 示例 2:
42+
43+
```python
44+
输入:equations = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]]
45+
输出:[3.75000,0.40000,5.00000,0.20000]
46+
```
1147

1248
## 解题思路
1349

50+
### 思路 1:并查集
51+
1452
在「[等式方程的可满足性](https://leetcode.cn/problems/satisfiability-of-equality-equations)」的基础上增加了倍数关系。在「[等式方程的可满足性](https://leetcode.cn/problems/satisfiability-of-equality-equations)」中我们处理传递关系使用了并查集,这道题也是一样,不过在使用并查集的同时还要维护倍数关系。
1553

1654
举例说明:
1755

18-
- `a / b = 2.0`:说明 `a = 2b``a``b` 在同一个集合。
19-
- `b / c = 3.0`:说明 `b = 3c``b``c` 在同一个集合。
56+
- `a / b = 2.0`:说明 $a == 2b$,$a$$b$ 在同一个集合。
57+
- `b / c = 3.0`:说明 $b == 3c$,$b$$c$ 在同一个集合。
2058

21-
根据上述两式可得:`a``b``c` 都在一个集合中,且 `a = 2b = 6c`
59+
根据上述两式可得:$a$、$b$、$c$ 都在一个集合中,且 $a == 2b == 6c$
2260

23-
我们可以将同一集合中的变量倍数关系都转换为与根节点变量的倍数关系,比如上述例子中都转变为与 `a` 的倍数关系。
61+
我们可以将同一集合中的变量倍数关系都转换为与根节点变量的倍数关系,比如上述例子中都转变为与 $a$ 的倍数关系。
2462

2563
具体操作如下:
2664

27-
- 定义并查集结构,并在并查集中定义一个表示倍数关系的 `multiples` 数组。
28-
- 遍历 `equations` 数组、`values` 数组,将每个变量按顺序编号,并使用 `union` 将其并入相同集合。
29-
- 遍历 `queries` 数组,判断两个变量是否在并查集中,并且是否在同一集合。如果找到对应关系,则将计算后的倍数关系存入答案数组,否则则将 `-1` 存入答案数组。
65+
- 定义并查集结构,并在并查集中定义一个表示倍数关系的 $multiples$ 数组。
66+
- 遍历 $equations$ 数组、$values$ 数组,将每个变量按顺序编号,并使用 `union` 将其并入相同集合。
67+
- 遍历 $queries$ 数组,判断两个变量是否在并查集中,并且是否在同一集合。如果找到对应关系,则将计算后的倍数关系存入答案数组,否则则将 $-1$ 存入答案数组。
3068
- 最终输出答案数组。
3169

3270
并查集中维护倍数相关方法说明:
@@ -36,11 +74,11 @@
3674
- `union` 方法:
3775
- 如果两个节点属于同一集合,则直接返回。
3876
- 如果两个节点不属于同一个集合,合并之前当前节点的倍数关系更新,然后再进行更新。
39-
- `is_connect` 方法:
40-
- 如果两个节点不属于同一集合,返回 `-1`
77+
- `is_connected` 方法:
78+
- 如果两个节点不属于同一集合,返回 $-1$
4179
- 如果两个节点属于同一集合,则返回倍数关系。
4280

43-
## 代码
81+
### 思路 1:代码
4482

4583
```python
4684
class UnionFind:
@@ -109,3 +147,8 @@ class Solution:
109147
return res
110148
```
111149

150+
### 思路 1:复杂度分析
151+
152+
- **时间复杂度**:$O((m + n) \times \alpha(m + n))$,$\alpha$ 是反 `Ackerman` 函数。
153+
- **空间复杂度**:$O(m + n)$。
154+

Solutions/0454. 四数相加 II.md

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,55 @@
55

66
## 题目大意
77

8-
给定四个整数数组 nums1、nums2、nums3、nums4。计算有多少不同的(i, j, k, l)满足 nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0。
8+
**描述**:给定四个整数数组 $nums1$、$nums2$、$nums3$、$nums4$。
9+
10+
**要求**:计算有多少不同的 $(i, j, k, l)$ 满足以下条件。
11+
12+
1. $0 \le i, j, k, l < n$。
13+
2. $nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0$。
14+
15+
**说明**
16+
17+
- $n == nums1.length$。
18+
- $n == nums2.length$。
19+
- $n == nums3.length$。
20+
- $n == nums4.length$。
21+
- $1 \le n \le 200$。
22+
- $-2^{28} \le nums1[i], nums2[i], nums3[i], nums4[i] \le 2^{28}$。
23+
24+
**示例**
25+
26+
- 示例 1:
27+
28+
```python
29+
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
30+
输出:2
31+
解释:
32+
两个元组如下:
33+
1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
34+
2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
35+
```
36+
37+
- 示例 2:
38+
39+
```python
40+
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
41+
输出:1
42+
```
943

1044
## 解题思路
1145

46+
### 思路 1:哈希表
47+
1248
直接暴力搜索的时间复杂度是 $O(n^4)$。我们可以降低一下复杂度。
1349

14-
将四个数组分为两组。nums1 和 nums2 分为一组,nums3 和 nums4 分为一组。
50+
将四个数组分为两组。$nums1$$nums2$ 分为一组,$nums3$$nums4$ 分为一组。
1551

16-
已知 $nums1[i] + nums2[j] + nums3[k] + nums4[l] = 0$,可以得到 $nums1[i] + nums2[j] = -(nums3[k] + nums4[l])$
52+
已知 $nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0$,可以得到 $nums1[i] + nums2[j] = -(nums3[k] + nums4[l])$
1753

18-
建立一个哈希表。两重循环遍历数组 nums1nums2,先将 $nums[i] + nums[j]$ 的和个数记录到哈希表中,然后再用两重循环遍历数组 nums3nums4。如果 $-(nums3[k] + nums4[l])$ 的结果出现在哈希表中,则将结果数累加到答案中。最终输出累加之后的答案。
54+
建立一个哈希表。两重循环遍历数组 $nums1$、$nums2$,先将 $nums[i] + nums[j]$ 的和个数记录到哈希表中,然后再用两重循环遍历数组 $nums3$、$nums4$。如果 $-(nums3[k] + nums4[l])$ 的结果出现在哈希表中,则将结果数累加到答案中。最终输出累加之后的答案。
1955

20-
## 代码
56+
### 思路 1:代码
2157

2258
```python
2359
class Solution:
@@ -40,3 +76,8 @@ class Solution:
4076
return count
4177
```
4278

79+
### 思路 1:复杂度分析
80+
81+
- **时间复杂度**:$O(n^2)$,其中 $n$ 为数组的元素个数。
82+
- **空间复杂度**:$O(n^2)$。
83+

Solutions/0705. 设计哈希集合.md

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,51 @@
55

66
## 题目大意
77

8-
要求不使用内建的哈希表库,自行实现一个哈希集合(HashSet)。
8+
**要求**:不使用内建的哈希表库,自行实现一个哈希集合(HashSet)。
99

10-
满足以下操作
10+
需要满足以下操作
1111

12-
- void add(key) 向哈希集合中插入值 key 。
13-
- bool contains(key) 返回哈希集合中是否存在这个值 key 。
14-
- void remove(key) 将给定值 key 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
12+
- `void add(key)` 向哈希集合中插入值 $key$。
13+
- `bool contains(key)` 返回哈希集合中是否存在这个值 $key$。
14+
- `void remove(key)` 将给定值 $key$ 从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
15+
16+
**说明**
17+
18+
- $0 \le key \le 10^6$。
19+
- 最多调用 $10^4$ 次 `add``remove``contains`
20+
21+
**示例**
22+
23+
- 示例 1:
24+
25+
```python
26+
输入:
27+
["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"]
28+
[[], [1], [2], [1], [3], [2], [2], [2], [2]]
29+
输出:
30+
[null, null, null, true, false, null, true, null, false]
31+
32+
解释:
33+
MyHashSet myHashSet = new MyHashSet();
34+
myHashSet.add(1); // set = [1]
35+
myHashSet.add(2); // set = [1, 2]
36+
myHashSet.contains(1); // 返回 True
37+
myHashSet.contains(3); // 返回 False ,(未找到)
38+
myHashSet.add(2); // set = [1, 2]
39+
myHashSet.contains(2); // 返回 True
40+
myHashSet.remove(2); // set = [1]
41+
myHashSet.contains(2); // 返回 False ,(已移除)
42+
```
1543

1644
## 解题思路
1745

18-
可以利用「数组+链表」的方式实现哈希集合。
46+
### 思路 1:数组 + 链表
47+
48+
定义一个一维长度为 $buckets$ 的二维数组 $table$。
1949

20-
定义一个一维长度为 buckets 的二维数组 table。第一维度用于计算哈希函数,为 key 分桶。第二个维度用于寻找 key 存放的具体位置。第二维度的数组会根据 key 值动态增长,模拟真正的链表。
50+
第一维度用于计算哈希函数,为 $key$ 进行分桶。第二个维度用于寻找 $key$ 存放的具体位置。第二维度的数组会根据 $key$ 值动态增长,模拟真正的链表。
2151

22-
## 代码
52+
### 思路 1:代码
2353

2454
```python
2555
class MyHashSet:
@@ -52,3 +82,8 @@ class MyHashSet:
5282
return key in self.table[hash_key]
5383
```
5484

85+
### 思路 1:复杂度分析
86+
87+
- **时间复杂度**:$O(\frac{n}{m})$,其中 $n$ 为哈希表中的元素数量,$b$ 为 $table$ 的元素个数,也就是链表的数量。
88+
- **空间复杂度**:$O(n + m)$。
89+

0 commit comments

Comments
 (0)