151. Reverse Words in a String**
https://leetcode.com/problems/reverse-words-in-a-string/
题目描述
Given an input string, reverse the string word by word.
Example 1:
Input: "the sky is blue"
Output: "blue is sky the"
Example 2:
Input: " hello world! "
Output: "world! hello"
Explanation: Your reversed string should not contain leading or trailing spaces.
Example 3:
Input: "a good example"
Output: "example good a"
Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string.
Note:
- A word is defined as a sequence of non-space characters.
- Input string may contain leading or trailing spaces. However, your reversed string should not contain leading or trailing spaces.
- You need to reduce multiple spaces between two words to a single space in the reversed string.
Follow up:
For C programmers, try to solve it in-place in O ( 1 ) O(1) O(1) extra space.
C++ 实现 1
如果使用 stringstream
来求解, 本题非常简单. 先给出简洁的解法, 再来考虑 in-place
的使用
O
(
1
)
O(1)
O(1) 空间的方法.
class Solution {
public:
string reverseWords(string &s) {
stringstream ss(s);
string word;
s = "";
while (ss >> word) {
s = word + " " + s;
}
// 上面 `word + " " + s` 这行代码会在 s 的末尾增加一个空格
// 此处要删除该空格
if (s != "") s = s.substr(0, s.size() - 1);
return s;
}
};
C++ 实现 2
(20210321 更新) C++ 实现 3
写的太复杂了, 没必要. 这题的基本思想就是先整体翻转, 然后再翻转其中的每个 word
.
访问每个字符 s[i]
, 如果不为空格的时候, 再通过 j
来查找每个 word = s[i, ..., j)
的范围.
class Solution {
public:
string reverseWords(string s) {
std::reverse(s.begin(), s.end());
string res;
for (int i = 0; i < s.size(); ++ i) {
if (s[i] != ' ') {
int j = i;
while (j < s.size() && s[j] != ' ') ++ j;
if (!res.empty()) res += " "; // res 如果不可为空字符串, 就可以在后面加上一个空格
auto = s.substr(i, j - i);
std::reverse(word.begin(), word.end());
res += word;
i = j;
}
}
return res;
}
};
C++ 实现 3
先依次翻转句子中的每个单词, 最后翻转整个句子. 难点在于对于空格的处理. 为了不申请额外的空间, 使用指针 k
来指示可以插入单词的位置.
class Solution {
public:
string reverseWords(string s) {
int k = 0;
for (int i = 0; i < s.size(); ++ i) {
if (s[i] == ' ') continue;
int j = i;
while (j < s.size() && s[j] != ' ') ++ j;
// j 指向 s.end() 或者句子中的空格处
if (j > i) {
std::reverse(s.begin() + i, s.begin() + j);
// 拷贝单词, 并增加一个空格
while (i < j) s[k++] = s[i++];
if (k < s.size()) s[k++] = ' ';
}
i = j;
}
// 注意此时 k 指向 s.end() 或者句子中的某处.
// 比如对于句子 " Hello world!", k 最后会
// 停留在有效句子(指的去除了中间多余的空格的句子)的末尾.
s = s.substr(0, k);
int i = 0, j = s.size() - 1;
// 删除多余的空格
while (i < s.size() && s[i] == ' ') ++ i;
while (j >= 0 && s[j] == ' ') -- j;
s = s.substr(i, j + 1);
std::reverse(s.begin(), s.end());
return s;
}
};
C++ 实现 4
更为直观的做法. 一看就懂, 但是使用了额外的空间.
class Solution {
public:
string reverseWords(string s) {
int k = 0;
string res;
for (int i = 0; i < s.size(); ++ i) {
if (s[i] == ' ') continue;
int j = i;
while (j < s.size() && s[j] != ' ') ++ j;
auto word = s.substr(i, j - i);
std::reverse(word.begin(), word.end());
res += word + " ";
i = j;
}
if (res.back() == ' ') res = res.substr(0, res.size() - 1);
std::reverse(res.begin(), res.end());
return res;
}
};