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 b1e24e9

Browse files
update change
2 parents 1d74967 + af4b5d0 commit b1e24e9

File tree

78 files changed

+1852
-1061
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1852
-1061
lines changed

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
如果你是算法老手,这篇攻略也是复习的最佳资料,如果把每个系列对应的总结篇,快速过一遍,整个算法知识体系以及各种解法就重现脑海了。
6363

6464

65-
目前「代码随想录」刷题攻略更新了:**200多篇文章,精讲了200道经典算法题目,共60w字的详细图解,部分难点题目还搭配了20分钟左右的视频讲解**
65+
目前「代码随想录」刷题攻略更新了:**200多篇文章,精讲了200道经典算法题目,共60w字的详细图解,大部分题目都搭配了20分钟左右的视频讲解**,视频质量很好,口碑很好,大家可以去看看,视频列表:[代码随想录视频讲解](https://www.bilibili.com/video/BV1fA4y1o715)
6666

6767
**这里每一篇题解,都是精品,值得仔细琢磨**
6868

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

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,21 +127,29 @@ Python:
127127
# def __init__(self, val=0, next=None):
128128
# self.val = val
129129
# self.next = next
130+
130131
class Solution:
131132
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
132-
head_dummy = ListNode()
133-
head_dummy.next = head
134-
135-
slow, fast = head_dummy, head_dummy
136-
while(n>=0): #fast先往前走n+1步
133+
# 创建一个虚拟节点,并将其下一个指针设置为链表的头部
134+
dummy_head = ListNode(0, head)
135+
136+
# 创建两个指针,慢指针和快指针,并将它们初始化为虚拟节点
137+
slow = fast = dummy_head
138+
139+
# 快指针比慢指针快 n+1 步
140+
for i in range(n+1):
137141
fast = fast.next
138-
n -= 1
139-
while(fast!=None):
142+
143+
# 移动两个指针,直到快速指针到达链表的末尾
144+
while fast:
140145
slow = slow.next
141146
fast = fast.next
142-
#fast 走到结尾后,slow的下一个节点为倒数第N个节点
143-
slow.next = slow.next.next #删除
144-
return head_dummy.next
147+
148+
# 通过更新第 (n-1) 个节点的 next 指针删除第 n 个节点
149+
slow.next = slow.next.next
150+
151+
return dummy_head.next
152+
145153
```
146154
Go:
147155
```Go

‎problems/0024.两两交换链表中的节点.md‎

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,21 +186,20 @@ Python:
186186

187187
class Solution:
188188
def swapPairs(self, head: ListNode) -> ListNode:
189-
res = ListNode(next=head)
190-
pre = res
189+
dummy_head = ListNode(next=head)
190+
current = dummy_head
191191

192-
# 必须有pre的下一个和下下个才能交换,否则说明已经交换结束了
193-
while pre.next and pre.next.next:
194-
cur = pre.next
195-
post = pre.next.next
192+
# 必须有cur的下一个和下下个才能交换,否则说明已经交换结束了
193+
while current.next and current.next.next:
194+
temp = current.next# 防止节点修改
195+
temp1 = current.next.next.next
196196

197-
# pre,cur,post对应最左,中间的,最右边的节点
198-
cur.next = post.next
199-
post.next = cur
200-
pre.next = post
197+
current.next = current.next.next
198+
current.next.next = temp
199+
temp.next = temp1
200+
current = current.next.next
201+
return dummy_head.next
201202

202-
pre = pre.next.next
203-
return res.next
204203
```
205204

206205
Go:

‎problems/0027.移除元素.md‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ Python:
198198

199199

200200
``` python 3
201+
(版本一)快慢指针法
201202
class Solution:
202203
def removeElement(self, nums: List[int], val: int) -> int:
203204
# 快慢指针
@@ -213,7 +214,21 @@ class Solution:
213214
return slow
214215
```
215216

216-
217+
``` python 3
218+
(版本二)暴力法
219+
class Solution:
220+
def removeElement(self, nums: List[int], val: int) -> int:
221+
i, l = 0, len(nums)
222+
while i < l:
223+
if nums[i] == val: # 找到等于目标值的节点
224+
for j in range(i+1, l): # 移除该元素,并将后面元素向前平移
225+
nums[j - 1] = nums[j]
226+
l -= 1
227+
i -= 1
228+
i += 1
229+
return l
230+
231+
```
217232

218233

219234
Go:

‎problems/0045.跳跃游戏II.md‎

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,20 @@ public:
7676
for (int i = 0; i < nums.size(); i++) {
7777
nextDistance = max(nums[i] + i, nextDistance); // 更新下一步覆盖最远距离下标
7878
if (i == curDistance) { // 遇到当前覆盖最远距离下标
79-
if (curDistance < nums.size() - 1) { // 如果当前覆盖最远距离下标不是终点
80-
ans++; // 需要走下一步
81-
curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
82-
if (nextDistance >= nums.size() - 1) break; // 下一步的覆盖范围已经可以达到终点,结束循环
83-
} else break; // 当前覆盖最远距到达集合终点,不用做ans++操作了,直接结束
79+
ans++; // 需要走下一步
80+
curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
81+
if (nextDistance >= nums.size() - 1) break; // 当前覆盖最远距到达集合终点,不用做ans++操作了,直接结束
8482
}
8583
}
8684
return ans;
8785
}
8886
};
8987
```
9088
89+
* 时间复杂度: O(n)
90+
* 空间复杂度: O(1)
91+
92+
9193
## 方法二
9294
9395
依然是贪心,思路和方法一差不多,代码可以简洁一些。
@@ -127,6 +129,11 @@ public:
127129
};
128130
```
129131

132+
* 时间复杂度: O(n)
133+
* 空间复杂度: O(1)
134+
135+
136+
130137
可以看出版本二的代码相对于版本一简化了不少!
131138

132139
**其精髓在于控制移动下标 i 只移动到 nums.size() - 2 的位置**,所以移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不用考虑别的了。
@@ -231,6 +238,21 @@ class Solution:
231238
step += 1
232239
return step
233240
```
241+
```python
242+
# 贪心版本三 - 类似‘55-跳跃游戏’写法
243+
class Solution:
244+
def jump(self, nums) -> int:
245+
if len(nums)==1: return 0
246+
i = 0
247+
count = 0
248+
cover = 0
249+
while i<=cover:
250+
for i in range(i,cover+1):
251+
cover = max(nums[i]+i,cover)
252+
if cover>=len(nums)-1: return count+1
253+
count+=1
254+
255+
```
234256

235257
```python
236258
# 动态规划做法

‎problems/0047.全排列II.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true) {
158158

159159
所以我通过举[1,1,1]的例子,把这两个去重的逻辑分别抽象成树形结构,大家可以一目了然:为什么两种写法都可以以及哪一种效率更高!
160160

161+
这里可能大家又有疑惑,既然 `used[i - 1] == false`也行而`used[i - 1] == true`也行,那为什么还要写这个条件呢?
162+
163+
直接这样写 不就完事了?
164+
165+
```cpp
166+
if (i > 0 && nums[i] == nums[i - 1]) {
167+
continue;
168+
}
169+
```
170+
171+
其实并不行,一定要加上 `used[i - 1] == false`或者`used[i - 1] == true`,因为 used[i - 1] 要一直是 true 或者一直是false 才可以,而不是 一会是true 一会又是false。 所以这个条件要写上。
172+
173+
161174
是不是豁然开朗了!!
162175

163176
## 其他语言版本

‎problems/0053.最大子序和.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
暴力解法的思路,第一层 for 就是设置起始位置,第二层 for 循环遍历数组寻找最大值
2626

27-
- 时间复杂度:O(n^2)
28-
- 空间复杂度:O(1)
2927

3028
```CPP
3129
class Solution {
@@ -44,6 +42,9 @@ public:
4442
}
4543
};
4644
```
45+
* 时间复杂度:O(n^2)
46+
* 空间复杂度:O(1)
47+
4748
4849
以上暴力的解法 C++勉强可以过,其他语言就不确定了。
4950
@@ -98,7 +99,6 @@ public:
9899
}
99100
};
100101
```
101-
102102
- 时间复杂度:O(n)
103103
- 空间复杂度:O(1)
104104

‎problems/0055.跳跃游戏.md‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050

5151
如图:
5252

53-
![55.跳跃游戏](https://code-thinking-1253855093.file.myqcloud.com/pics/20201124154758229-20230310135019977.png)
53+
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20230203105634.png)
54+
5455

5556
i 每次移动只能在 cover 的范围内移动,每移动一个元素,cover 得到该元素数值(新的覆盖范围)的补充,让 i 继续移动下去。
5657

@@ -75,6 +76,10 @@ public:
7576
};
7677
```
7778
79+
* 时间复杂度: O(n)
80+
* 空间复杂度: O(1)
81+
82+
7883
## 总结
7984
8085
这道题目关键点在于:不用拘泥于每次究竟跳几步,而是看覆盖范围,覆盖范围内一定是可以跳过来的,不用管是怎么跳的。

‎problems/0056.合并区间.md‎

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ public:
7373
};
7474
```
7575

76+
* 时间复杂度: O(nlogn)
77+
* 空间复杂度: O(logn),排序需要的空间开销
78+
79+
7680
## 其他语言版本
7781

7882

@@ -109,7 +113,6 @@ class Solution {
109113
}
110114
}
111115

112-
}
113116
```
114117
```java
115118
// 版本2
@@ -308,24 +311,22 @@ object Solution {
308311

309312
```Rust
310313
impl Solution {
311-
fn max(a: i32, b: i32) -> i32 {
312-
if a > b { a } else { b }
313-
}
314-
315-
pub fn merge(intervals: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
316-
let mut intervals = intervals;
317-
let mut result = Vec::new();
318-
if intervals.len() == 0 { return result; }
319-
intervals.sort_by(|a, b| a[0].cmp(&b[0]));
320-
result.push(intervals[0].clone());
321-
for i in 1..intervals.len() {
322-
if result.last_mut().unwrap()[1] >= intervals[i][0] {
323-
result.last_mut().unwrap()[1] = Self::max(result.last_mut().unwrap()[1], intervals[i][1]);
314+
pub fn merge(mut intervals: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
315+
let mut res = vec![];
316+
if intervals.is_empty() {
317+
return res;
318+
}
319+
intervals.sort_by_key(|a| a[0]);
320+
res.push(intervals[0].clone());
321+
for interval in intervals.into_iter().skip(1) {
322+
let res_last_ele = res.last_mut().unwrap();
323+
if res_last_ele[1] >= interval[0] {
324+
res_last_ele[1] = interval[1].max(res_last_ele[1]);
324325
} else {
325-
result.push(intervals[i].clone());
326+
res.push(interval);
326327
}
327328
}
328-
result
329+
res
329330
}
330331
}
331332
```

‎problems/0062.不同路径.md‎

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -395,21 +395,14 @@ function uniquePaths(m: number, n: number): number {
395395
```Rust
396396
impl Solution {
397397
pub fn unique_paths(m: i32, n: i32) -> i32 {
398-
let m = m as usize;
399-
let n = n as usize;
400-
let mut dp = vec![vec![0; n]; m];
401-
for i in 0..m {
402-
dp[i][0] = 1;
403-
}
404-
for j in 0..n {
405-
dp[0][j] = 1;
406-
}
407-
for i in 1..m {
408-
for j in 1..n {
409-
dp[i][j] = dp[i-1][j] + dp[i][j-1];
410-
}
398+
let (m, n) = (m as usize, n as usize);
399+
let mut dp = vec![vec![1; n]; m];
400+
for i in 1..m {
401+
for j in 1..n {
402+
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
411403
}
412-
dp[m-1][n-1]
404+
}
405+
dp[m - 1][n - 1]
413406
}
414407
}
415408
```

0 commit comments

Comments
(0)

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