Movatterモバイル変換


[0]ホーム

URL:


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

Commitd97ac95

Browse files
Update
1 parent494b9c0 commitd97ac95

File tree

6 files changed

+159
-34
lines changed

6 files changed

+159
-34
lines changed

‎README.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,7 @@
4747
*[数组:总结篇](https://mp.weixin.qq.com/s/LIfQFRJBH5ENTZpvixHEmg)
4848
*[字符串:这道题目,使用库函数一行代码搞定](https://mp.weixin.qq.com/s/X02S61WCYiCEhaik6VUpFA)
4949
*[字符串:简单的反转还不够!](https://mp.weixin.qq.com/s/XGSk1GyPWhfqj2g7Cb1Vgw)
50-
* 精选链表相关的面试题
51-
* 精选字符串相关的面试题
52-
* 精选栈与队列相关的面试题
53-
* 精选二叉树相关的面试题
54-
* 精选递归与回溯面试题
55-
50+
*[字符串:替换空格](https://mp.weixin.qq.com/s/t0A9C44zgM-RysAQV3GZpg)
5651

5752
(持续更新中....)
5853

‎pics/51.N皇后.png

122 KB
Loading

‎pics/51.N皇后1.png

18.6 KB
Loading

‎problems/0001.两数之和.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public:
5555
if(iter != map.end()) {
5656
return {iter->second, i};
5757
}
58-
map.insert(nums[i], i);
58+
map.insert(pair<int, int>(nums[i], i));
5959
}
6060
return {};
6161
}

‎problems/0051.N皇后.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,49 @@ n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并
3636

3737
#思路
3838

39+
都知道n皇后问题是回溯算法解决的经典问题,但是用回溯解决多了 排列,组合,子集问题之后,遇到这种二位矩阵还会有点不知所措。
40+
41+
首先来看一下皇后们的约束条件:
42+
43+
1. 不能同行
44+
2. 不能同列
45+
3. 不能同斜线
46+
47+
48+
确定完约束条件,来看看究竟要怎么去搜索皇后们的位置,其实搜索皇后的位置,可以抽象为一棵树。
49+
50+
下面我用一个3 * 3 的棋牌,如图:
51+
52+
<imgsrc='../pics/51.N皇后1.png'width=600> </img></div>
53+
54+
将搜索过程抽象为一颗树,如图:
55+
56+
57+
<imgsrc='../pics/51.N皇后.png'width=600> </img></div>
58+
59+
从图中,可以看出,二维矩阵,其实矩阵的行,就是 这颗树的高度,矩阵的宽就是二叉树没一个节点孩子的宽度。
60+
61+
62+
那么我们用皇后们的约束条件,来回溯搜索这颗二叉树,**只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了。**
63+
64+
我总结的回溯模板如下:
65+
66+
```
67+
backtracking() {
68+
if (终止条件) {
69+
存放结果;
70+
}
71+
72+
for (枚举同一个位置的所有可能性,可以想成节点孩子的数量) {
73+
递归,处理节点;
74+
backtracking();
75+
回溯,撤销处理结果
76+
}
77+
}
78+
```
79+
80+
那么按照这个模板不能写出如下代码:
81+
3982
#C++代码
4083

4184
```

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

Lines changed: 114 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,41 @@
22
##题目地址
33
https://leetcode-cn.com/problems/reverse-words-in-a-string/
44

5-
##思路
5+
>综合考察字符串操作的好题。
66
7-
这道题目可以说是综合考察了字符串的多种操作。
7+
#题目:151.翻转字符串里的单词
88

9-
那么问题来了,要不要使用split 和 reverse 等等库函数
9+
给定一个字符串,逐个翻转字符串中的每个单词。
1010

11-
这道题目中很多同学使用库函数走捷径解题,其实这也无可厚非,如果这样做,一定要确保自己可以实现这些库函数的功能,别看 split 好像很简单,其实很多时候自己去实现的时候错漏百出的。
11+
示例 1:
12+
输入: "the sky is blue"
13+
输出: "blue is sky the"
1214

13-
解题思路:
15+
示例 2:
16+
输入: "  hello world!  "
17+
输出: "world! hello"
18+
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
19+
20+
示例 3:
21+
输入: "a good   example"
22+
输出: "example good a"
23+
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
24+
25+
26+
#思路
27+
28+
**这道题目可以说是综合考察了字符串的多种操作。**
29+
30+
31+
一些同学会使用split库函数,分隔单词,然后定义一个新的string字符串,最后再把单词倒序相加,那么这道题题目就是一道水题了,失去了它的意义。
32+
33+
所以这里我还是提高一下本题的难度:**不要使用辅助空间,空间复杂度要求为O(1)。**
34+
35+
不能使用辅助空间之后,那么只能在原字符串上下功夫了。
36+
37+
想一下,我们将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒叙了,那么再把单词反转一下,单词不就正过来了。
38+
39+
所以解题思路如下:
1440

1541
* 移除多余空格
1642
* 将整个字符串反转
@@ -22,7 +48,86 @@ https://leetcode-cn.com/problems/reverse-words-in-a-string/
2248

2349
这样我们就完成了翻转字符串里的单词。
2450

25-
##代码
51+
思路很明确了,我们说一说代码的实现细节,就拿移除多余空格来说,一些同学会上来写如下代码:
52+
53+
```
54+
void removeExtraSpaces(string& s) {
55+
for (int i = s.size() - 1; i > 0; i--) {
56+
if (s[i] == s[i - 1] && s[i] == ' ') {
57+
s.erase(s.begin() + i);
58+
}
59+
}
60+
// 删除字符串最后面的空格
61+
if (s.size() > 0 && s[s.size() - 1] == ' ') {
62+
s.erase(s.begin() + s.size() - 1);
63+
}
64+
// 删除字符串最前面的空格
65+
if (s.size() > 0 && s[0] == ' ') {
66+
s.erase(s.begin());
67+
}
68+
}
69+
```
70+
71+
逻辑很简单,从前向后遍历,遇到空格了就erase。
72+
73+
如果不仔细琢磨一下erase的时间复杂读,还以为以上的代码是O(n)的时间复杂度呢。
74+
75+
想一下真正的时间复杂度是多少,一个erase本来就是O(n)的操作,erase实现原理题目:[数组:就移除个元素很难么?](https://mp.weixin.qq.com/s/wj0T-Xs88_FHJFwayElQlA),最优的算法来移除元素也要O(n)。
76+
77+
erase操作上面还套了一个for循环,那么以上代码移除冗余空格的代码时间复杂度为O(n^2)。
78+
79+
那么使用双指针法来去移除空格,最后resize(重新设置)一下字符串的大小,就可以做到O(n)的时间复杂度。
80+
81+
如果对这个操作比较生疏了,可以再看一下这篇文章:[数组:就移除个元素很难么?](https://mp.weixin.qq.com/s/wj0T-Xs88_FHJFwayElQlA)是如何移除元素的。
82+
83+
那么使用双指针来移除冗余空格代码如下: fastIndex走的快,slowIndex走的慢,最后slowIndex就标记着移除多余空格后新字符串的长度。
84+
85+
```
86+
void removeExtraSpaces(string& s) {
87+
int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针
88+
// 去掉字符串前面的空格
89+
while (s.size() > 0 && fastIndex < s.size() && s[fastIndex] == ' ') {
90+
fastIndex++;
91+
}
92+
for (; fastIndex < s.size(); fastIndex++) {
93+
// 去掉字符串中间部分的冗余空格
94+
if (fastIndex - 1 > 0
95+
&& s[fastIndex - 1] == s[fastIndex]
96+
&& s[fastIndex] == ' ') {
97+
continue;
98+
} else {
99+
s[slowIndex++] = s[fastIndex];
100+
}
101+
}
102+
if (slowIndex - 1 > 0 && s[slowIndex - 1] == ' ') { // 去掉字符串末尾的空格
103+
s.resize(slowIndex - 1);
104+
} else {
105+
s.resize(slowIndex); // 重新设置字符串大小
106+
}
107+
}
108+
```
109+
110+
有的同学可能发现用erase来移除空格,在leetcode上性能也还行。主要是以下几点;:
111+
112+
1. leetcode上的测试集里,字符串的长度不够长,如果足够长,性能差距会非常明显。
113+
2. leetcode的测程序耗时不是很准确的。
114+
115+
此时我们已经实现了removeExtraSpaces函数来移除冗余空格。
116+
117+
还做实现反转字符串的功能,支持反转字符串子区间,这个实现我们分别在[字符串:这道题目,使用库函数一行代码搞定](https://mp.weixin.qq.com/s/X02S61WCYiCEhaik6VUpFA)[字符串:简单的反转还不够!](https://mp.weixin.qq.com/s/XGSk1GyPWhfqj2g7Cb1Vgw)里已经讲过了。
118+
119+
代码如下:
120+
121+
```
122+
// 反转字符串s中左闭又闭的区间[start, end]
123+
void reverse(string& s, int start, int end) {
124+
for (int i = start, j = end; i < j; i++, j--) {
125+
swap(s[i], s[j]);
126+
}
127+
}
128+
```
129+
130+
##本题C++整体代码
26131

27132
效率:
28133

@@ -33,13 +138,12 @@ class Solution {
33138
public:
34139
// 反转字符串s中左闭又闭的区间[start, end]
35140
void reverse(string& s, int start, int end) {
36-
int offset = (end - start + 1) / 2;
37-
for (int i = start, j = end; i < start + offset; i++, j--) {
141+
for (int i = start, j = end; i < j; i++, j--) {
38142
swap(s[i], s[j]);
39143
}
40144
}
41-
// 字符串去掉冗余的空格
42-
//使用快慢指针发
145+
146+
//移除冗余空格:使用双指针(快慢指针法)O(n)的算法
43147
void removeExtraSpaces(string& s) {
44148
int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针
45149
// 去掉字符串前面的空格
@@ -63,23 +167,6 @@ public:
63167
}
64168
}
65169
66-
// 费时间的写法
67-
void removeExtraSpaces1(string& s) {
68-
for (int i = s.size() - 1; i > 0; i--) {
69-
if (s[i] == s[i - 1] && s[i] == ' ') {
70-
s.erase(s.begin() + i);
71-
}
72-
}
73-
// 删除字符串最后面的空格
74-
if (s.size() > 0 && s[s.size() - 1] == ' ') {
75-
s.erase(s.begin() + s.size() - 1);
76-
}
77-
// 删除字符串最前面的空格
78-
if (s.size() > 0 && s[0] == ' ') {
79-
s.erase(s.begin());
80-
}
81-
}
82-
83170
string reverseWords(string s) {
84171
removeExtraSpaces(s); // 去掉冗余空格
85172
reverse(s, 0, s.size() - 1); // 将字符串全部反转

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp