题目描述
给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
示例1:
输入: s = “Let’s take LeetCode contest”
输出:“s’teL ekat edoCteeL tsetnoc”
示例2:
输入: s = “God Ding”
输出: “doG gniD”
提示
- 1 <= s.length <= 5 * 104
- s 包含可打印的 ASCII 字符。
- s 不包含任何开头或结尾空格。
- s 里 至少有一个词。
- s 中的所有单词都用一个空格隔开。
方法一
解题思路
直接在原字符串上进行操作,避免开辟额外的空间。
判断单词的方法是:如果遇到不是空格的字符,便把这第一个字符标记为 start,并不断往后遍历字符串,遇到空格或字符串结束便停止循环,把空格或 ‘\0’ 的前一个字符标记为 end。
然后使用反转字符串的方法在原空间上翻转单词。
反转字符串的方法:交换字符串第一个字符与倒数第一个字符,随后交换字符串第二个字符与倒数第二个字符,如此往复,便可以反转字符串。
代码
class Solution {
public:
string reverseWords(string s) {
int n = s.size();
int i = 0;
while(i < n)
{
if(s[i] != ' ')
{
// 单词起始标志
int start = i;
while(s[i] != ' ' && s[i]) i++;
// 单词结束标志
int end = i - 1;
// 翻转单词
while(start < end)
{
char t = s[start];
s[start] = s[end];
s[end] = t;
start++;
end--;
}
}
i++;
}
return s;
}
};
复杂度分析
- 时间复杂度:O(n)。
- 空间复杂度:O(1)。不需要额外开辟空间。
方法二
解题思路
需要开辟一个新字符串。
用判断单词的方法确定 start 和 end 标志,把 [start, end] 范围内的字符倒序存入新字符串中,并判断此时的 s[i] 是否为空格,并在字符串中加入空格。
代码
class Solution {
public:
string reverseWords(string s) {
string ans;
int n = s.size();
int i = 0;
while(i < n)
{
if(s[i] != ' ')
{
int start = i;
while(s[i] != ' ' && s[i]) i++;
int end = i - 1;
while(start <= end)
{
ans.push_back(s[end--]);
}
if(s[i] == ' ') ans.push_back(' ');
}
i++;
}
return ans;
}
};
复杂度分析
- 时间复杂度:O(n)。
- 空间复杂度:O(n)。需要额外开辟空间。