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 9b56f0a

Browse files
Merge branch 'youngyangyang04:master' into master
2 parents 7ead616 + a8382d9 commit 9b56f0a

27 files changed

+1267
-180
lines changed

‎problems/0015.三数之和.md‎

Lines changed: 24 additions & 18 deletions
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‎

Lines changed: 1 addition & 1 deletion
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‎

Lines changed: 64 additions & 0 deletions
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‎

Lines changed: 50 additions & 34 deletions
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

‎problems/0084.柱状图中最大的矩形.md‎

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,128 @@ class Solution:
474474

475475
### Go:
476476

477-
> 单调栈
477+
暴力解法
478+
479+
```go
480+
func largestRectangleArea(heights []int) int {
481+
sum := 0
482+
for i := 0; i < len(heights); i++ {
483+
left, right := i, i
484+
for left >= 0 {
485+
if heights[left] < heights[i] {
486+
break
487+
}
488+
left--
489+
}
490+
for right < len(heights) {
491+
if heights[right] < heights[i] {
492+
break
493+
}
494+
right++
495+
}
496+
w := right - left - 1
497+
h := heights[i]
498+
sum = max(sum, w * h)
499+
}
500+
return sum
501+
}
502+
503+
func max(x, y int) int {
504+
if x > y {
505+
return x
506+
}
507+
return y
508+
}
509+
```
510+
511+
双指针解法
512+
513+
```go
514+
func largestRectangleArea(heights []int) int {
515+
size := len(heights)
516+
minLeftIndex := make([]int, size)
517+
minRightIndex := make([]int, size)
518+
519+
// 记录每个柱子 左边第一个小于该柱子的下标
520+
minLeftIndex[0] = -1 // 注意这里初始化,防止下面while死循环
521+
for i := 1; i < size; i++ {
522+
t := i - 1
523+
// 这里不是用if,而是不断向左寻找的过程
524+
for t >= 0 && heights[t] >= heights[i] {
525+
t = minLeftIndex[t]
526+
}
527+
minLeftIndex[i] = t
528+
}
529+
// 记录每个柱子 右边第一个小于该柱子的下标
530+
minRightIndex[size - 1] = size; // 注意这里初始化,防止下面while死循环
531+
for i := size - 2; i >= 0; i-- {
532+
t := i + 1
533+
// 这里不是用if,而是不断向右寻找的过程
534+
for t < size && heights[t] >= heights[i] {
535+
t = minRightIndex[t]
536+
}
537+
minRightIndex[i] = t
538+
}
539+
// 求和
540+
result := 0
541+
for i := 0; i < size; i++ {
542+
sum := heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1)
543+
result = max(sum, result)
544+
}
545+
return result
546+
}
547+
548+
func max(x, y int) int {
549+
if x > y {
550+
return x
551+
}
552+
return y
553+
}
554+
```
555+
556+
单调栈
557+
558+
```go
559+
func largestRectangleArea(heights []int) int {
560+
result := 0
561+
heights = append([]int{0}, heights...) // 数组头部加入元素0
562+
heights = append(heights, 0) // 数组尾部加入元素0
563+
st := []int{0}
564+
565+
// 第一个元素已经入栈,从下标1开始
566+
for i := 1; i < len(heights); i++ {
567+
if heights[i] > heights[st[len(st)-1]] {
568+
st = append(st, i)
569+
} else if heights[i] == heights[st[len(st)-1]] {
570+
st = st[:len(st)-1]
571+
st = append(st, i)
572+
} else {
573+
for len(st) > 0 && heights[i] < heights[st[len(st)-1]] {
574+
mid := st[len(st)-1]
575+
st = st[:len(st)-1]
576+
if len(st) > 0 {
577+
left := st[len(st)-1]
578+
right := i
579+
w := right - left - 1
580+
h := heights[mid]
581+
result = max(result, w * h)
582+
}
583+
}
584+
st = append(st, i)
585+
}
586+
}
587+
return result
588+
}
589+
590+
func max(x, y int) int {
591+
if x > y {
592+
return x
593+
}
594+
return y
595+
}
596+
```
597+
598+
单调栈精简
478599

479600
```go
480601
func largestRectangleArea(heights []int) int {

0 commit comments

Comments
(0)

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