Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b4ffe82

Browse files
committed
更新题解列表
1 parent 059ab18 commit b4ffe82

8 files changed

+275
-34
lines changed

‎Solutions/0028. 找出字符串中第一个匹配项的下标.md‎

Lines changed: 130 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,30 @@
2020
```Python
2121
输入:haystack = "hello", needle = "ll"
2222
输出:2
23+
解释:"sad" 在下标 06 处匹配。第一个匹配项的下标是 0 ,所以返回 0
24+
25+
输入:haystack = "leetcode", needle = "leeto"
26+
输出:-1
27+
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1
2328
```
2429

2530
## 解题思路
2631

2732
字符串匹配的经典题目。常见的字符串匹配算法有:BF(Brute Force)算法、RK(Robin-Karp)算法、KMP(Knuth Morris Pratt)算法、BM(Boyer Moore)算法、Horspool 算法、Sunday 算法等。
2833

29-
### 思路 1:BF(Brute Force)算法代码
34+
### 思路 1:BF(Brute Force)算法
35+
36+
**BF 算法思想**:对于给定文本串 `T` 与模式串 `p`,从文本串的第一个字符开始与模式串 `p` 的第一个字符进行比较,如果相等,则继续逐个比较后续字符,否则从文本串 `T` 的第二个字符起重新和模式串 `p` 进行比较。依次类推,直到模式串 `p` 中每个字符依次与文本串 `T` 的一个连续子串相等,则模式匹配成功。否则模式匹配失败。
37+
38+
BF 算法具体步骤如下:
39+
40+
1. 对于给定的文本串 `T` 与模式串 `p`,求出文本串 `T` 的长度为 `n`,模式串 `p` 的长度为 `m`
41+
2. 同时遍历文本串 `T` 和模式串 `p`,先将 `T[0]``p[0]` 进行比较。
42+
1. 如果相等,则继续比较 `T[1]``p[1]`。以此类推,一直到模式串 `p` 的末尾 `p[m - 1]` 为止。
43+
2. 如果不相等,则将文本串 `T` 移动到上次匹配开始位置的下一个字符位置,模式串 `p` 则回退到开始位置,再依次进行比较。
44+
3. 当遍历完文本串 `T` 或者模式串 `p` 的时候停止搜索。
45+
46+
### 思路 1:代码
3047

3148
```Python
3249
class Solution:
@@ -50,8 +67,28 @@ class Solution:
5067
return -1
5168
```
5269

70+
### 思路 1:复杂度分析
71+
72+
- **时间复杂度**:平均时间复杂度为 $O(n + m),ドル最坏时间复杂度为 $O(m \times n)$。其中文本串 $T$ 的长度为 $n,ドル模式串 $p$ 的长度为 $m$。
73+
- **空间复杂度**:$O(1)$。
74+
75+
### 思路 2:RK(Robin Karp)算法
76+
77+
**RK 算法思想**:对于给定文本串 `T` 与模式串 `p`,通过滚动哈希算快速筛选出与模式串 `p` 不匹配的文本位置,然后在其余位置继续检查匹配项。
78+
79+
RK 算法具体步骤如下:
80+
81+
1. 对于给定的文本串 `T` 与模式串 `p`,求出文本串 `T` 的长度为 `n`,模式串 `p` 的长度为 `m`
82+
2. 通过滚动哈希算法求出模式串 `p` 的哈希值 `hash_p`
83+
3. 再通过滚动哈希算法对文本串 `T``n - m + 1` 个子串分别求哈希值 `hash_t`
84+
4. 然后逐个与模式串的哈希值比较大小。
85+
1. 如果当前子串的哈希值 `hash_t` 与模式串的哈希值 `hash_p` 不同,则说明两者不匹配,则继续向后匹配。
86+
2. 如果当前子串的哈希值 `hash_t` 与模式串的哈希值 `hash_p` 相等,则验证当前子串和模式串的每个字符是否真的相等(避免哈希冲突)。
87+
1. 如果当前子串和模式串的每个字符相等,则说明当前子串和模式串匹配。
88+
2. 如果当前子串和模式串的每个字符不相等,则说明两者不匹配,继续向后匹配。
89+
5. 比较到末尾,如果仍未成功匹配,则说明文本串 `T` 中不包含模式串 `p`,方法返回 `-1`
5390

54-
### 思路 2:RK(Robin-Karp)算法代码
91+
### 思路 2:代码
5592

5693
```Python
5794
class Solution:
@@ -75,7 +112,26 @@ class Solution:
75112
return rabinKarp(haystack, needle)
76113
```
77114

78-
### 思路 3:KMP(Knuth Morris Pratt)算法代码
115+
### 思路 1:复杂度分析
116+
117+
- **时间复杂度**:$O(n)$。其中文本串 $T$ 的长度为 $n,ドル模式串 $p$ 的长度为 $m$。
118+
- **空间复杂度**:$O(m)$。
119+
120+
### 思路 3:KMP(Knuth Morris Pratt)算法
121+
122+
**KMP 算法思想**:对于给定文本串 `T` 与模式串 `p`,当发现文本串 `T` 的某个字符与模式串 `p` 不匹配的时候,可以利用匹配失败后的信息,尽量减少模式串与文本串的匹配次数,避免文本串位置的回退,以达到快速匹配的目的。
123+
124+
KMP 算法具体步骤如下:
125+
126+
1. 根据 `next` 数组的构造步骤生成「前缀表」`next`
127+
2. 使用两个指针 `i``j`,其中 `i` 指向文本串中当前匹配的位置,`j` 指向模式串中当前匹配的位置。初始时,`i = 0`,`j = 0`
128+
3. 循环判断模式串前缀是否匹配成功,如果模式串前缀匹配不成功,将模式串进行回退,即 `j = next[j - 1]`,直到 `j == 0` 时或前缀匹配成功时停止回退。
129+
4. 如果当前模式串前缀匹配成功,则令模式串向右移动 `1` 位,即 `j += 1`
130+
5. 如果当前模式串 **完全** 匹配成功,则返回模式串 `p` 在文本串 `T` 中的开始位置,即 `i - j + 1`
131+
6. 如果还未完全匹配成功,则令文本串向右移动 `1` 位,即 `i += 1`,然后继续匹配。
132+
7. 如果直到文本串遍历完也未完全匹配成功,则说明匹配失败,返回 `-1`
133+
134+
### 思路 3:代码
79135

80136
```Python
81137
class Solution:
@@ -120,7 +176,29 @@ class Solution:
120176
return kmp(haystack, needle)
121177
```
122178

123-
### 思路 4:BM(Boyer Moore)算法代码
179+
### 思路 3:复杂度分析
180+
181+
- **时间复杂度**:$O(n + m),ドル其中文本串 $T$ 的长度为 $n,ドル模式串 $p$ 的长度为 $m$。
182+
- **空间复杂度**:$O(m)$。
183+
184+
### 思路 4:BM(Boyer Moore)算法
185+
186+
**BM 算法思想**:对于给定文本串 `T` 与模式串 `p`,先对模式串 `p` 进行预处理。然后在匹配的过程中,当发现文本串 `T` 的某个字符与模式串 `p` 不匹配的时候,根据启发策略,能够直接尽可能地跳过一些无法匹配的情况,将模式串多向后滑动几位。
187+
188+
BM 算法具体步骤如下:
189+
190+
1. 计算出文本串 `T` 的长度为 `n`,模式串 `p` 的长度为 `m`
191+
2. 先对模式串 `p` 进行预处理,生成坏字符位置表 `bc_table` 和好后缀规则后移位数表 `gs_talbe`
192+
3. 将模式串 `p` 的头部与文本串 `T` 对齐,将 `i` 指向文本串开始位置,即 `i = 0``j` 指向模式串末尾位置,即 `j = m - 1`,然后从模式串末尾位置开始进行逐位比较。
193+
1. 如果文本串对应位置 `T[i + j]` 上的字符与 `p[j]` 相同,则继续比较前一位字符。
194+
1. 如果模式串全部匹配完毕,则返回模式串 `p` 在文本串中的开始位置 `i`
195+
2. 如果文本串对应位置 `T[i + j]` 上的字符与 `p[j]` 不相同,则:
196+
1. 根据坏字符位置表计算出在「坏字符规则」下的移动距离 `bad_move`
197+
2. 根据好后缀规则后移位数表计算出在「好后缀规则」下的移动距离 `good_mode`
198+
3. 取两种移动距离的最大值,然后对模式串进行移动,即 `i += max(bad_move, good_move)`
199+
4. 如果移动到末尾也没有找到匹配情况,则返回 `-1`
200+
201+
### 思路 4:代码
124202

125203
```Python
126204
class Solution:
@@ -182,7 +260,27 @@ class Solution:
182260
return boyerMoore(haystack, needle)
183261
```
184262

185-
### 思路 5:Horspool 算法代码
263+
### 思路 4:复杂度分析
264+
265+
- **时间复杂度**:$O(n + \sigma),ドル其中文本串 $T$ 的长度为 $n,ドル字符集的大小是 $\sigma$。
266+
- **空间复杂度**:$O(m)$。其中模式串 $p$ 的长度为 $m$。
267+
268+
### 思路 5:Horspool 算法
269+
270+
**Horspool 算法思想**:对于给定文本串 `T` 与模式串 `p`,先对模式串 `p` 进行预处理。然后在匹配的过程中,当发现文本串 `T` 的某个字符与模式串 `p` 不匹配的时候,根据启发策略,能够尽可能的跳过一些无法匹配的情况,将模式串多向后滑动几位。
271+
272+
Horspool 算法具体步骤如下:
273+
274+
1. 计算出文本串 `T` 的长度为 `n`,模式串 `p` 的长度为 `m`
275+
2. 先对模式串 `p` 进行预处理,生成后移位数表 `bc_table`
276+
3. 将模式串 `p` 的头部与文本串 `T` 对齐,将 `i` 指向文本串开始位置,即 `i = 0``j` 指向模式串末尾位置,即 `j = m - 1`,然后从模式串末尾位置开始比较。
277+
1. 如果文本串对应位置的字符 `T[i + j]` 与模式串对应字符 `p[j]` 相同,则继续比较前一位字符。
278+
1. 如果模式串全部匹配完毕,则返回模式串 `p` 在文本串中的开始位置 `i`
279+
2. 如果文本串对应位置的字符 `T[i + j]` 与模式串对应字符 `p[j]` 不同,则:
280+
1. 根据后移位数表 `bc_table` 和模式串末尾位置对应的文本串上的字符 `T[i + m - 1]` ,计算出可移动距离 `bc_table[T[i + m - 1]]`,然后将模式串进行后移。
281+
4. 如果移动到末尾也没有找到匹配情况,则返回 `-1`
282+
283+
### 思路 5:代码
186284

187285
```Python
188286
class Solution:
@@ -215,7 +313,27 @@ class Solution:
215313
return horspool(haystack, needle)
216314
```
217315

218-
### 思路 6:Sunday 算法代码
316+
### 思路 5:复杂度分析
317+
318+
- **时间复杂度**:$O(n)$。其中文本串 $T$ 的长度为 $n$。
319+
- **空间复杂度**:$O(m)$。其中模式串 $p$ 的长度为 $m$。
320+
321+
### 思路 6:Sunday 算法
322+
323+
**Sunday 算法思想**:对于给定文本串 `T` 与模式串 `p`,先对模式串 `p` 进行预处理。然后在匹配的过程中,当发现文本串 `T` 的某个字符与模式串 `p` 不匹配的时候,根据启发策略,能够尽可能的跳过一些无法匹配的情况,将模式串多向后滑动几位。
324+
325+
Sunday 算法具体步骤如下:
326+
327+
1. 计算出文本串 `T` 的长度为 `n`,模式串 `p` 的长度为 `m`
328+
2. 先对模式串 `p` 进行预处理,生成后移位数表 `bc_table`
329+
3. 将模式串 `p` 的头部与文本串 `T` 对齐,将 `i` 指向文本串开始位置,即 `i = 0``j` 指向模式串末尾位置,即 `j = m - 1`,然后从模式串末尾位置开始比较。
330+
1. 如果文本串对应位置的字符 `T[i + j]` 与模式串对应字符 `p[j]` 相同,则继续比较前一位字符。
331+
1. 如果模式串全部匹配完毕,则返回模式串 `p` 在文本串中的开始位置 `i`
332+
2. 如果文本串对应位置的字符 `T[i + j]` 与模式串对应字符 `p[j]` 不同,则:
333+
1. 根据后移位数表 `bc_table` 和模式串末尾位置对应的文本串上的字符 `T[i + m - 1]` ,计算出可移动距离 `bc_table[T[i + m - 1]]`,然后将模式串进行后移。
334+
4. 如果移动到末尾也没有找到匹配情况,则返回 `-1`
335+
336+
### 思路 6:代码
219337

220338
```Python
221339
class Solution:
@@ -248,4 +366,9 @@ class Solution:
248366
return bc_table
249367

250368
return sunday(haystack, needle)
251-
```
369+
```
370+
371+
### 思路 6:复杂度分析
372+
373+
- **时间复杂度**:$O(n)$。其中文本串 $T$ 的长度为 $n$。
374+
- **空间复杂度**:$O(m)$。其中模式串 $p$ 的长度为 $m$。

‎Solutions/0036. 有效的数独.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@
4545

4646
判断数独有效,需要分别看每一行、每一列、每一个 `3 * 3` 的小方格是否出现了重复数字,如果都没有出现重复数字就是一个有效的数独,如果出现了重复数字则不是有效的数独。
4747

48-
-`3``9 * 9` 的数组分别来表示该数字是否在所在的行,所在的列,所在的方格出现过。其中方格角标的计算用 `box[(i/3)*3+(j/3)][n]` 来表示。
48+
-`3``9 * 9` 的数组分别来表示该数字是否在所在的行,所在的列,所在的方格出现过。其中方格角标的计算用 `box[(i / 3) * 3 + (j / 3)][n]` 来表示。
4949
- 双重循环遍历数独矩阵。如果对应位置上的数字如果已经在在所在的行 / 列 / 方格出现过,则返回 `False`
5050
- 遍历完没有重复出现,则返回 `Ture`
5151

52-
### 思路 1:哈希表代码
52+
### 思路 1:代码
5353

5454
```Python
5555
class Solution:
@@ -76,3 +76,7 @@ class Solution:
7676
return True
7777
```
7878

79+
### 思路 1:复杂度分析
80+
81+
- **时间复杂度**:$O(1)$。数独总共 81 个单元格,对每个单元格遍历一次,可以看做是常数级的时间复杂度。
82+
- **空间复杂度**:$O(1)$。使用 81 个单位空间,可以看做是常数级的空间复杂度。

‎Solutions/0125. 验证回文串.md‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,3 @@ class Solution:
6767

6868
- **时间复杂度**:$O(len(s))$。
6969
- **空间复杂度**:$O(len(s))$。
70-

‎Solutions/0217. 存在重复元素.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
```Python
2020
输入:nums = [1,2,3,1]
2121
输出:True
22+
23+
输入:nums = [1,2,3,4]
24+
输出:False
2225
```
2326

2427
## 解题思路
@@ -43,6 +46,11 @@ class Solution:
4346
return False
4447
```
4548

49+
### 思路 1:复杂度分析
50+
51+
- **时间复杂度**:$O(n)$。
52+
- **空间复杂度**:$O(n)$。
53+
4654
### 思路 2:集合
4755

4856
- 使用一个 `set` 集合存储数组中所有元素。
@@ -57,6 +65,11 @@ class Solution:
5765
return len(set(nums)) != len(nums)
5866
```
5967

68+
### 思路 2:复杂度分析
69+
70+
- **时间复杂度**:$O(n)$。
71+
- **空间复杂度**:$O(n)$。
72+
6073
### 思路 3:排序
6174

6275
- 对数组进行排序。
@@ -75,3 +88,8 @@ class Solution:
7588
return True
7689
return False
7790
```
91+
92+
### 思路 3:复杂度分析
93+
94+
- **时间复杂度**:$O(n \times \log n)$。
95+
- **空间复杂度**:$O(1)$。

‎Solutions/0219. 存在重复元素 II.md‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,22 @@
3434
- 判断哈希表长度是否超过了 `k`,如果超过了 `k`,则删除哈希表中最旧的元素 `nums[i - k]`
3535
- 如果遍历完仍旧找不到,则返回 `False`
3636

37-
### 思路 1:哈希表代码
37+
### 思路 1:代码
3838

3939
```Python
4040
class Solution:
4141
def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
42-
nums_set = set()
42+
nums_dict = dict()
4343
for i in range(len(nums)):
44-
if nums[i] in nums_set:
44+
if nums[i] in nums_dict:
4545
return True
46-
nums_set.add(nums[i])
47-
if len(nums_set) > k:
48-
nums_set.remove(nums[i - k])
46+
nums_dict[nums[i]] =1
47+
if len(nums_dict) > k:
48+
del nums_dict[nums[i - k]]
4949
return False
5050
```
5151

52+
### 思路 1:复杂度分析
53+
54+
- **时间复杂度**:$O(n)$。
55+
- **空间复杂度**:$O(n)$。

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

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,36 @@
55

66
## 题目大意
77

8-
给定两个数组,编写一个函数来计算它们的交集。输出结果中,需要考虑元素出现的次数。
8+
**描述**:给定两个数组 `nums1``nums2`
9+
10+
**要求**:返回两个数组的交集。可以不考虑输出结果的顺序。
11+
12+
**说明**:
13+
14+
- 输出结果中,每个元素出现的次数,应该与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。
15+
- 1ドル \le nums1.length, nums2.length \le 1000$。
16+
- 0ドル \le nums1[i], nums2[i] \le 1000$。
17+
18+
**示例**:
19+
20+
```Python
21+
输入:nums1 = [1,2,2,1], nums2 = [2,2]
22+
输出:[2,2]
23+
24+
25+
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
26+
输出:[4,9]
27+
```
928

1029
## 解题思路
1130

12-
先遍历第一个数组,利用字典来存放第一个数组的元素出现次数。
31+
### 思路 1:哈希表
1332

14-
然后遍历第二个数组,如果字典中存在该元素,则将该元素加入到答案数组中,并减少字典中该元素出现的次数。
33+
1. 先遍历第一个数组,利用字典来存放第一个数组的元素出现次数。
34+
2. 然后遍历第二个数组,如果字典中存在该元素,则将该元素加入到答案数组中,并减少字典中该元素出现的次数。
35+
3. 遍历完之后,返回答案数组。
1536

16-
##代码
37+
### 思路 1:代码
1738

1839
```Python
1940
class Solution:
@@ -32,3 +53,7 @@ class Solution:
3253
return nums
3354
```
3455

56+
### 思路 1:复杂度分析
57+
58+
- **时间复杂度**:$O(n)$。
59+
- **空间复杂度**:$O(n)$。

‎Solutions/0557. 反转字符串中的单词 III.md‎

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,48 @@
55

66
## 题目大意
77

8-
给定一个字符串 s,将字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
8+
**描述**:给定一个字符串 `s`
9+
10+
**要求**:将字符串中每个单词的字符顺序进行反装,同时仍保留空格和单词的初始顺序。
11+
12+
**说明**:
13+
14+
- 1ドル \le s.length \le 5 * 10^4$。
15+
- `s` 包含可打印的 ASCII 字符。
16+
- `s` 不包含任何开头或结尾空格。
17+
- `s` 里至少有一个词。
18+
- `s` 中的所有单词都用一个空格隔开。
19+
20+
**示例**:
21+
22+
```Python
23+
输入:s = "Let's take LeetCode contest"
24+
输出:"s'teL ekat edoCteeL tsetnoc"
25+
26+
27+
输入: s = "God Ding"
28+
输出:"doG gniD"
29+
```
930

1031
## 解题思路
1132

33+
### 思路 1:使用额外空间
34+
1235
因为 Python 的字符串是不可变的,所以在原字符串空间上进行切换顺序操作肯定是不可行的了。但我们可以利用切片方法。
1336

14-
- 将字符串按空格进行分割,分割成一个个的单词。
15-
- 再将每个单词进行反转。
16-
- 然后再将每个单词连接起来
37+
1. 将字符串按空格进行分割,分割成一个个的单词。
38+
2. 再将每个单词进行反转。
39+
3. 最后将每个单词连接起来
1740

18-
##代码
41+
### 思路 1:代码
1942

2043
```Python
2144
class Solution:
2245
def reverseWords(self, s: str) -> str:
2346
return " ".join(word[::-1] for word in s.split(" "))
2447
```
2548

49+
### 思路 1:复杂度分析
50+
51+
- **时间复杂度**:$O(n)$。
52+
- **空间复杂度**:$O(n)$。

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /