Skip to content

Commit ff8b3e9

Browse files
Update
1 parent 648df89 commit ff8b3e9

19 files changed

+508
-130
lines changed

problems/0015.三数之和.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
# 思路
3131

32+
针对本题,我录制了视频讲解:[梦破碎的地方!| LeetCode:15.三数之和](https://www.bilibili.com/video/BV1GW4y127qo),结合本题解一起看,事半功倍!
33+
3234
**注意[0, 0, 0, 0] 这组数据**
3335

3436
## 哈希解法

problems/0018.四数之和.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
# 思路
3131

32+
针对本题,我录制了视频讲解:[难在去重和剪枝!| LeetCode:18. 四数之和](https://www.bilibili.com/video/BV1DS4y147US),结合本题解一起看,事半功倍!
33+
3234
四数之和,和[15.三数之和](https://programmercarl.com/0015.三数之和.html)是一个思路,都是使用双指针法, 基本解法就是在[15.三数之和](https://programmercarl.com/0015.三数之和.html) 的基础上再套一层for循环。
3335

3436
但是有一些细节需要注意,例如: 不要判断`nums[k] > target` 就返回了,三数之和 可以通过 `nums[i] > 0` 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是`[-4, -3, -2, -1]``target``-10`,不能因为`-4 > -10`而跳过。但是我们依旧可以去做剪枝,逻辑变成`nums[i] > target && (nums[i] >=0 || target >= 0)`就可以了。

problems/0027.移除元素.md

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

2929
## 思路
3030

31-
[本题B站视频讲解](https://www.bilibili.com/video/BV12A4y1Z7LP)
31+
针对本题,我录制了视频讲解:[数组中移除元素并不容易!LeetCode:27. 移除元素](https://www.bilibili.com/video/BV12A4y1Z7LP),结合本题解一起看,事半功倍!
3232

3333
有的同学可能说了,多余的元素,删掉不就得了。
3434

problems/0059.螺旋矩阵II.md

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

2525
## 思路
2626

27-
为了利于录友们理解,我特意录制了视频,[拿下螺旋矩阵,《代码随想录》第五题!](https://www.bilibili.com/video/BV1SL4y1N7mV)结合本篇文章一起看,效果更佳。
27+
为了利于录友们理解,我特意录制了视频,[拿下螺旋矩阵!LeetCode:59.螺旋矩阵II](https://www.bilibili.com/video/BV1SL4y1N7mV)结合视频一起看,事半功倍!
2828

2929
这道题目可以说在面试中出现频率较高的题目,**本题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。**
3030

problems/0134.加油站.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,9 @@ public:
7777
};
7878
```
7979
80-
* 时间复杂度:$O(n^2)$
81-
* 空间复杂度:$O(1)$
80+
* 时间复杂度:O(n^2)
81+
* 空间复杂度:O(1)
8282
83-
C++暴力解法在leetcode上提交也可以过。
8483
8584
## 贪心算法(方法一)
8685

problems/0151.翻转字符串里的单词.md

Lines changed: 33 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@
3131

3232
# 思路
3333

34-
**这道题目可以说是综合考察了字符串的多种操作。**
34+
针对本题,我录制了视频讲解:[字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词](https://www.bilibili.com/video/BV1uT41177fX),结合本题解一起看,事半功倍!
3535

36+
**这道题目可以说是综合考察了字符串的多种操作。**
3637

3738
一些同学会使用split库函数,分隔单词,然后定义一个新的string字符串,最后再把单词倒序相加,那么这道题题目就是一道水题了,失去了它的意义。
3839

@@ -81,17 +82,14 @@ void removeExtraSpaces(string& s) {
8182
8283
如果不仔细琢磨一下erase的时间复杂度,还以为以上的代码是O(n)的时间复杂度呢。
8384
84-
想一下真正的时间复杂度是多少,一个erase本来就是O(n)的操作,erase实现原理题目:[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html),最优的算法来移除元素也要O(n)
85+
想一下真正的时间复杂度是多少,一个erase本来就是O(n)的操作。
8586
8687
erase操作上面还套了一个for循环,那么以上代码移除冗余空格的代码时间复杂度为O(n^2)。
8788
8889
那么使用双指针法来去移除空格,最后resize(重新设置)一下字符串的大小,就可以做到O(n)的时间复杂度。
8990
90-
如果对这个操作比较生疏了,可以再看一下这篇文章:[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html)是如何移除元素的。
91-
92-
那么使用双指针来移除冗余空格代码如下: fastIndex走的快,slowIndex走的慢,最后slowIndex就标记着移除多余空格后新字符串的长度。
93-
9491
```CPP
92+
//版本一
9593
void removeExtraSpaces(string& s) {
9694
int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针
9795
// 去掉字符串前面的空格
@@ -121,120 +119,58 @@ void removeExtraSpaces(string& s) {
121119
1. leetcode上的测试集里,字符串的长度不够长,如果足够长,性能差距会非常明显。
122120
2. leetcode的测程序耗时不是很准确的。
123121

124-
此时我们已经实现了removeExtraSpaces函数来移除冗余空格。
122+
版本一的代码是比较如何一般思考过程,就是 先移除字符串钱的空格,在移除中间的,在移除后面部分。
125123

126-
还做实现反转字符串的功能,支持反转字符串子区间,这个实现我们分别在[344.反转字符串](https://programmercarl.com/0344.反转字符串.html)[541.反转字符串II](https://programmercarl.com/0541.反转字符串II.html)里已经讲过了。
124+
不过其实还可以优化,这部分和[27.移除元素](https://programmercarl.com/0027.移除元素.html)的逻辑是一样一样的,本题是移除空格,而 27.移除元素 就是移除元素。
127125

128-
代码如下
126+
所以代码可以写的很精简,大家可以看 如下 代码 removeExtraSpaces 函数的实现
129127

130-
```
131-
// 反转字符串s中左闭又闭的区间[start, end]
132-
void reverse(string& s, int start, int end) {
133-
for (int i = start, j = end; i < j; i++, j--) {
134-
swap(s[i], s[j]);
128+
```CPP
129+
// 版本二
130+
void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。
131+
int slow = 0; //整体思想参考https://programmercarl.com/0027.移除元素.html
132+
for (int i = 0; i < s.size(); ++i) { //
133+
if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
134+
if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
135+
while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束。
136+
s[slow++] = s[i++];
137+
}
138+
}
135139
}
140+
s.resize(slow); //slow的大小即为去除多余空格后的大小。
136141
}
137142
```
138143
139-
本题C++整体代码
144+
如果以上代码看不懂,建议先把 [27.移除元素](https://programmercarl.com/0027.移除元素.html)这道题目做了,或者看视频讲解:[数组中移除元素并不容易!LeetCode:27. 移除元素](https://www.bilibili.com/video/BV12A4y1Z7LP) 。
140145
146+
此时我们已经实现了removeExtraSpaces函数来移除冗余空格。
141147
142-
```CPP
143-
// 版本一
144-
class Solution {
145-
public:
146-
// 反转字符串s中左闭又闭的区间[start, end]
147-
void reverse(string& s, int start, int end) {
148-
for (int i = start, j = end; i < j; i++, j--) {
149-
swap(s[i], s[j]);
150-
}
151-
}
148+
还做实现反转字符串的功能,支持反转字符串子区间,这个实现我们分别在[344.反转字符串](https://programmercarl.com/0344.反转字符串.html)和[541.反转字符串II](https://programmercarl.com/0541.反转字符串II.html)里已经讲过了。
152149
153-
// 移除冗余空格:使用双指针(快慢指针法)O(n)的算法
154-
void removeExtraSpaces(string& s) {
155-
int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针
156-
// 去掉字符串前面的空格
157-
while (s.size() > 0 && fastIndex < s.size() && s[fastIndex] == ' ') {
158-
fastIndex++;
159-
}
160-
for (; fastIndex < s.size(); fastIndex++) {
161-
// 去掉字符串中间部分的冗余空格
162-
if (fastIndex - 1 > 0
163-
&& s[fastIndex - 1] == s[fastIndex]
164-
&& s[fastIndex] == ' ') {
165-
continue;
166-
} else {
167-
s[slowIndex++] = s[fastIndex];
168-
}
169-
}
170-
if (slowIndex - 1 > 0 && s[slowIndex - 1] == ' ') { // 去掉字符串末尾的空格
171-
s.resize(slowIndex - 1);
172-
} else {
173-
s.resize(slowIndex); // 重新设置字符串大小
174-
}
175-
}
150+
代码如下:
176151
177-
string reverseWords(string s) {
178-
removeExtraSpaces(s); // 去掉冗余空格
179-
reverse(s, 0, s.size() - 1); // 将字符串全部反转
180-
int start = 0; // 反转的单词在字符串里起始位置
181-
int end = 0; // 反转的单词在字符串里终止位置
182-
bool entry = false; // 标记枚举字符串的过程中是否已经进入了单词区间
183-
for (int i = 0; i < s.size(); i++) { // 开始反转单词
184-
if (!entry) {
185-
start = i; // 确定单词起始位置
186-
entry = true; // 进入单词区间
187-
}
188-
// 单词后面有空格的情况,空格就是分词符
189-
if (entry && s[i] == ' ' && s[i - 1] != ' ') {
190-
end = i - 1; // 确定单词终止位置
191-
entry = false; // 结束单词区间
192-
reverse(s, start, end);
193-
}
194-
// 最后一个结尾单词之后没有空格的情况
195-
if (entry && (i == (s.size() - 1)) && s[i] != ' ' ) {
196-
end = i;// 确定单词终止位置
197-
entry = false; // 结束单词区间
198-
reverse(s, start, end);
199-
}
200-
}
201-
return s;
202-
}
203-
204-
// 当然这里的主函数reverseWords写的有一些冗余的,可以精简一些,精简之后的主函数为:
205-
/* 主函数简单写法
206-
string reverseWords(string s) {
207-
removeExtraSpaces(s);
208-
reverse(s, 0, s.size() - 1);
209-
for(int i = 0; i < s.size(); i++) {
210-
int j = i;
211-
// 查找单词间的空格,翻转单词
212-
while(j < s.size() && s[j] != ' ') j++;
213-
reverse(s, i, j - 1);
214-
i = j;
215-
}
216-
return s;
152+
```CPP
153+
// 反转字符串s中左闭又闭的区间[start, end]
154+
void reverse(string& s, int start, int end) {
155+
for (int i = start, j = end; i < j; i++, j--) {
156+
swap(s[i], s[j]);
217157
}
218-
*/
219-
};
158+
}
220159
```
221160

222-
效率:
223-
<img src='https://code-thinking.cdn.bcebos.com/pics/151_翻转字符串里的单词.png' width=600> </img></div>
161+
整体代码如下:
224162

225163
```CPP
226-
//版本二:
227-
//原理同版本1,更简洁实现。
228164
class Solution {
229165
public:
230-
void reverse(string& s, int start, int end){ //翻转,区间写法:闭区间 []
166+
void reverse(string& s, int start, int end){ //翻转,区间写法:左闭又闭 []
231167
for (int i = start, j = end; i < j; i++, j--) {
232168
swap(s[i], s[j]);
233169
}
234170
}
235171

236172
void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。
237-
int slow = 0; //整体思想参考Leetcode: 27. 移除元素:https://leetcode.cn/problems/remove-element/
173+
int slow = 0; //整体思想参考https://programmercarl.com/0027.移除元素.html
238174
for (int i = 0; i < s.size(); ++i) { //
239175
if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
240176
if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
@@ -261,6 +197,7 @@ public:
261197
};
262198
```
263199
200+
264201
## 其他语言版本
265202
266203

0 commit comments

Comments
 (0)