151.反转字符串中的单词
力扣链接(中等):https://leetcode.cn/problems/reverse-words-in-a-string
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
Text Only |
---|
| 输入:s = "the sky is blue"
输出:"blue is sky the"
|
示例 2:
Text Only |
---|
| 输入:s = " hello world "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。
|
示例 3:
Text Only |
---|
| 输入:s = "a good example"
输出:"example good a"
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
|
提示:
1 <= s.length <= 104
s
包含英文大小写字母、数字和空格 ' '
s
中 至少存在一个 单词
进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1)
额外空间复杂度的 原地 解法。
个人题解
常规解法
C++ |
---|
| class Solution {
public:
string reverseWords(string s) {
string res;
if (s == "")
return res;
int left = 0, right = s.size() - 1;
// 过滤首位空格
while(left < right && s[left] == ' ')
left ++;
while(left < right && s[right] == ' ')
right --;
int i = right, j = right;
while(j >= left) {
while(i != left - 1 && s[i] != ' ')
i --;
// 写入单词
int k = i + 1;
while(k <= j)
res += s[k++];
res += ' ';
// 跳过单词前的空格
while (i >= left && s[i] == ' ')
i --;
j = i;
}
res.pop_back();
return res;
}
};
|
原地解法:空间复杂度 O(1)
C++ |
---|
| class Solution {
public:
// 去除前后和单词间的空白
void removeExtraSpaces(string &s) {
int slow = 0;
for (int i = 0; i < s.size(); i ++) {
// 不是空格的时候才处理,代表忽略了所有的空格
if(s[i] != ' ') {
// 如果slow不等于0,代表有单词了,在单词后面加一个空格即可
if(slow != 0) s[slow++] = ' ';
// 存入当前单词,遇到空格代表单词结束
while(i < s.size() && s[i] != ' ')
s[slow++] = s[i++];
}
}
// 重置string的长度
s.resize(slow);
}
void reverse(string &s, int begin, int end) {
for(int i = begin, j = end; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
string reverseWords(string s) {
// 首先去除多余的空格
removeExtraSpaces(s);
// 字符串整体反转
reverse(s, 0, s.size() - 1);
// 记录局部反转的起始位置
int start = 0;
for(int i = 0; i <= s.size(); i ++){
// 遇到单词结尾空格,或遇到字符串末尾时都需要局部反转
if(s[i] == ' ' || i == s.size()) {
reverse(s, start, i - 1);
start = i + 1;
}
}
return s;
}
};
|