Skip to content

Commit bd1bca9

Browse files
Merge branch 'master' into master
2 parents 6776ecc + 7fdb784 commit bd1bca9

39 files changed

+1989
-691
lines changed

README.md

+14-28
Original file line numberDiff line numberDiff line change
@@ -299,24 +299,25 @@
299299
<img src='https://code-thinking.cdn.bcebos.com/pics/动态规划-背包问题总结.png' width=500 alt='背包问题大纲'> </img></div>
300300

301301

302-
11. [动态规划:01背包理论基础](./problems/背包理论基础01背包-1.md)
303-
12. [动态规划:01背包理论基础(滚动数组](./problems/背包理论基础01背包-2.md)
302+
11. [动态规划:01背包理论基础(二维dp数组)](./problems/背包理论基础01背包-1.md)
303+
12. [动态规划:01背包理论基础(一维dp数组](./problems/背包理论基础01背包-2.md)
304304
13. [动态规划:416.分割等和子集](./problems/0416.分割等和子集.md)
305305
14. [动态规划:1049.最后一块石头的重量II](./problems/1049.最后一块石头的重量II.md)
306306
15. [本周小结!(动态规划系列三)](./problems/周总结/20210121动规周末总结.md)
307307
16. [动态规划:494.目标和](./problems/0494.目标和.md)
308308
17. [动态规划:474.一和零](./problems/0474.一和零.md)
309-
18. [动态规划:完全背包总结篇](./problems/背包问题理论基础完全背包.md)
310-
19. [动态规划:518.零钱兑换II](./problems/0518.零钱兑换II.md)
311-
20. [本周小结!(动态规划系列四)](./problems/周总结/20210128动规周末总结.md)
312-
21. [动态规划:377.组合总和Ⅳ](./problems/0377.组合总和Ⅳ.md)
313-
22. [动态规划:70.爬楼梯(完全背包版本)](./problems/0070.爬楼梯完全背包版本.md)
314-
23. [动态规划:322.零钱兑换](./problems/0322.零钱兑换.md)
315-
24. [动态规划:279.完全平方数](./problems/0279.完全平方数.md)
316-
25. [本周小结!(动态规划系列五)](./problems/周总结/20210204动规周末总结.md)
317-
26. [动态规划:139.单词拆分](./problems/0139.单词拆分.md)
318-
27. [动态规划:多重背包理论基础](./problems/背包问题理论基础多重背包.md)
319-
28. [背包问题总结篇](./problems/背包总结篇.md)
309+
18. [动态规划:完全背包理论基础(二维dp数组)](./problems/背包问题理论基础完全背包.md)
310+
19. [动态规划:完全背包理论基础(一维dp数组)](./problems/背包问题完全背包一维.md)
311+
20. [动态规划:518.零钱兑换II](./problems/0518.零钱兑换II.md)
312+
21. [本周小结!(动态规划系列四)](./problems/周总结/20210128动规周末总结.md)
313+
22. [动态规划:377.组合总和Ⅳ](./problems/0377.组合总和Ⅳ.md)
314+
23. [动态规划:70.爬楼梯(完全背包版本)](./problems/0070.爬楼梯完全背包版本.md)
315+
24. [动态规划:322.零钱兑换](./problems/0322.零钱兑换.md)
316+
25. [动态规划:279.完全平方数](./problems/0279.完全平方数.md)
317+
26. [本周小结!(动态规划系列五)](./problems/周总结/20210204动规周末总结.md)
318+
27. [动态规划:139.单词拆分](./problems/0139.单词拆分.md)
319+
28. [动态规划:多重背包理论基础](./problems/背包问题理论基础多重背包.md)
320+
29. [背包问题总结篇](./problems/背包总结篇.md)
320321

321322
打家劫舍系列:
322323

@@ -408,21 +409,6 @@
408409

409410
(持续更新中....)
410411

411-
412-
## 十大排序
413-
414-
## 数论
415-
416-
## 高级数据结构经典题目
417-
418-
* 并查集
419-
* 最小生成树
420-
* 线段树
421-
* 树状数组
422-
* 字典树
423-
424-
## 海量数据处理
425-
426412
# 补充题目
427413

428414
以上题目是重中之重,大家至少要刷两遍以上才能彻底理解,如果熟练以上题目之后还在找其他题目练手,可以再刷以下题目:

problems/0015.三数之和.md

+24-18
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
### 哈希解法
3636

37-
两层for循环就可以确定 a 和b 的数值了,可以使用哈希法来确定 0-(a+b) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。
37+
两层for循环就可以确定 两个数值,可以使用哈希法来确定 第三个数 0-(a+b) 或者 0 - (a + c) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。
3838

3939
把符合条件的三元组放进vector中,然后再去重,这样是非常费时的,很容易超时,也是这道题目通过率如此之低的根源所在。
4040

@@ -48,35 +48,41 @@
4848
```CPP
4949
class Solution {
5050
public:
51+
// 在一个数组中找到3个数形成的三元组,它们的和为0,不能重复使用(三数下标互不相同),且三元组不能重复。
52+
// b(存储)== 0-(a+c)(检索)
5153
vector<vector<int>> threeSum(vector<int>& nums) {
5254
vector<vector<int>> result;
5355
sort(nums.begin(), nums.end());
54-
// 找出a + b + c = 0
55-
// a = nums[i], b = nums[j], c = -(a + b)
56+
5657
for (int i = 0; i < nums.size(); i++) {
57-
// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组
58-
if (nums[i] > 0) {
58+
// 如果a是正数,a<b<c,不可能形成和为0的三元组
59+
if (nums[i] > 0)
5960
break;
60-
}
61-
if (i > 0 && nums[i] == nums[i - 1]) { //三元组元素a去重
61+
62+
// [a, a, ...] 如果本轮a和上轮a相同,那么找到的b,c也是相同的,所以去重a
63+
if (i > 0 && nums[i] == nums[i - 1])
6264
continue;
63-
}
65+
66+
// 这个set的作用是存储b
6467
unordered_set<int> set;
65-
for (int j = i + 1; j < nums.size(); j++) {
66-
if (j > i + 2
67-
&& nums[j] == nums[j-1]
68-
&& nums[j-1] == nums[j-2]) { // 三元组元素b去重
68+
69+
for (int k = i + 1; k < nums.size(); k++) {
70+
// 去重b=c时的b和c
71+
if (k > i + 2 && nums[k] == nums[k - 1] && nums[k - 1] == nums[k - 2])
6972
continue;
73+
74+
// a+b+c=0 <=> b=0-(a+c)
75+
int target = 0 - (nums[i] + nums[k]);
76+
if (set.find(target) != set.end()) {
77+
result.push_back({nums[i], target, nums[k]}); // nums[k]成为c
78+
set.erase(target);
7079
}
71-
int c = 0 - (nums[i] + nums[j]);
72-
if (set.find(c) != set.end()) {
73-
result.push_back({nums[i], nums[j], c});
74-
set.erase(c);// 三元组元素c去重
75-
} else {
76-
set.insert(nums[j]);
80+
else {
81+
set.insert(nums[k]); // nums[k]成为b
7782
}
7883
}
7984
}
85+
8086
return result;
8187
}
8288
};

problems/0019.删除链表的倒数第N个节点.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
* fast和slow同时移动,直到fast指向末尾,如题:
6060
<img src='https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B92.png' width=600> </img></div>
61-
61+
//图片中有错别词:应该将“只到”改为“直到”
6262
* 删除slow指向的下一个节点,如图:
6363
<img src='https://code-thinking.cdn.bcebos.com/pics/19.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B93.png' width=600> </img></div>
6464

problems/0028.实现strStr.md

+64
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,70 @@ public int[] GetNext(string needle)
14561456
}
14571457
```
14581458

1459+
### C:
1460+
1461+
> 前缀表统一右移和减一
1462+
1463+
```c
1464+
1465+
int *build_next(char* needle, int len) {
1466+
1467+
int *next = (int *)malloc(len * sizeof(int));
1468+
assert(next); // 确保分配成功
1469+
1470+
// 初始化next数组
1471+
next[0] = -1; // next[0] 设置为 -1,表示没有有效前缀匹配
1472+
if (len <= 1) { // 如果模式串长度小于等于 1,直接返回
1473+
return next;
1474+
}
1475+
next[1] = 0; // next[1] 设置为 0,表示第一个字符没有公共前后缀
1476+
1477+
// 构建next数组, i 从模式串的第三个字符开始, j 指向当前匹配的最长前缀长度
1478+
int i = 2, j = 0;
1479+
while (i < len) {
1480+
if (needle[i - 1] == needle[j]) {
1481+
j++;
1482+
next[i] = j;
1483+
i++;
1484+
} else if (j > 0) {
1485+
// 如果不匹配且 j > 0, 回退到次长匹配前缀的长度
1486+
j = next[j];
1487+
} else {
1488+
next[i] = 0;
1489+
i++;
1490+
}
1491+
}
1492+
return next;
1493+
}
1494+
1495+
int strStr(char* haystack, char* needle) {
1496+
1497+
int needle_len = strlen(needle);
1498+
int haystack_len = strlen(haystack);
1499+
1500+
int *next = build_next(needle, needle_len);
1501+
1502+
int i = 0, j = 0; // i 指向主串的当前起始位置, j 指向模式串的当前匹配位置
1503+
while (i <= haystack_len - needle_len) {
1504+
if (haystack[i + j] == needle[j]) {
1505+
j++;
1506+
if (j == needle_len) {
1507+
free(next);
1508+
next = NULL
1509+
return i;
1510+
}
1511+
} else {
1512+
i += j - next[j]; // 调整主串的起始位置
1513+
j = j > 0 ? next[j] : 0;
1514+
}
1515+
}
1516+
1517+
free(next);
1518+
next = NULL;
1519+
return -1;
1520+
}
1521+
```
1522+
14591523
<p align="center">
14601524
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
14611525
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>

problems/0037.解数独.md

+50-34
Original file line numberDiff line numberDiff line change
@@ -366,40 +366,56 @@ class Solution:
366366
"""
367367
Do not return anything, modify board in-place instead.
368368
"""
369-
self.backtracking(board)
370-
371-
def backtracking(self, board: List[List[str]]) -> bool:
372-
# 若有解,返回True;若无解,返回False
373-
for i in range(len(board)): # 遍历行
374-
for j in range(len(board[0])): # 遍历列
375-
# 若空格内已有数字,跳过
376-
if board[i][j] != '.': continue
377-
for k in range(1, 10):
378-
if self.is_valid(i, j, k, board):
379-
board[i][j] = str(k)
380-
if self.backtracking(board): return True
381-
board[i][j] = '.'
382-
# 若数字1-9都不能成功填入空格,返回False无解
383-
return False
384-
return True # 有解
385-
386-
def is_valid(self, row: int, col: int, val: int, board: List[List[str]]) -> bool:
387-
# 判断同一行是否冲突
388-
for i in range(9):
389-
if board[row][i] == str(val):
390-
return False
391-
# 判断同一列是否冲突
392-
for j in range(9):
393-
if board[j][col] == str(val):
394-
return False
395-
# 判断同一九宫格是否有冲突
396-
start_row = (row // 3) * 3
397-
start_col = (col // 3) * 3
398-
for i in range(start_row, start_row + 3):
399-
for j in range(start_col, start_col + 3):
400-
if board[i][j] == str(val):
401-
return False
402-
return True
369+
row_used = [set() for _ in range(9)]
370+
col_used = [set() for _ in range(9)]
371+
box_used = [set() for _ in range(9)]
372+
for row in range(9):
373+
for col in range(9):
374+
num = board[row][col]
375+
if num == ".":
376+
continue
377+
row_used[row].add(num)
378+
col_used[col].add(num)
379+
box_used[(row // 3) * 3 + col // 3].add(num)
380+
self.backtracking(0, 0, board, row_used, col_used, box_used)
381+
382+
def backtracking(
383+
self,
384+
row: int,
385+
col: int,
386+
board: List[List[str]],
387+
row_used: List[List[int]],
388+
col_used: List[List[int]],
389+
box_used: List[List[int]],
390+
) -> bool:
391+
if row == 9:
392+
return True
393+
394+
next_row, next_col = (row, col + 1) if col < 8 else (row + 1, 0)
395+
if board[row][col] != ".":
396+
return self.backtracking(
397+
next_row, next_col, board, row_used, col_used, box_used
398+
)
399+
400+
for num in map(str, range(1, 10)):
401+
if (
402+
num not in row_used[row]
403+
and num not in col_used[col]
404+
and num not in box_used[(row // 3) * 3 + col // 3]
405+
):
406+
board[row][col] = num
407+
row_used[row].add(num)
408+
col_used[col].add(num)
409+
box_used[(row // 3) * 3 + col // 3].add(num)
410+
if self.backtracking(
411+
next_row, next_col, board, row_used, col_used, box_used
412+
):
413+
return True
414+
board[row][col] = "."
415+
row_used[row].remove(num)
416+
col_used[col].remove(num)
417+
box_used[(row // 3) * 3 + col // 3].remove(num)
418+
return False
403419
```
404420

405421
### Go

0 commit comments

Comments
 (0)