题目:
给定一个字符串,逐个翻转字符串中的每个单词。
示例 1:
输入: "the sky is blue"
输出: "blue is sky the"
示例 2:
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
说明:
无空格字符构成一个单词。
输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
进阶:
请选用 C 语言的用户尝试使用 O(1) 额外空间复杂度的原地解法。
分析:
- 方法一:比较容易想出来,定义两个string变量,temp和ret,temp用来存储不包含空格的临时元素,遇到空格或到达数组末尾,将temp与ret合并;难点是对于逻辑的判断见代码1
- 方法二:希望通过O1空间实现原地翻转,所以不能借助临时的string变量;
将s先进行整体翻转,之后将首尾多余空格删除,使用首尾指针记录当前窗口位置,对整个数组进行遍历(更新窗口),遇到空格便将之前的窗口进行翻转;见代码2
代码1:ac
class Solution {
public:
string reverseWords(string s) {
int m = s.size(), i = 0;
string temp = "", ret = "";
for(int i = 0; i < m; i++)
{
if(s[i] != ' '){
temp+= s[i];
}
if( s[i] == ' ' && temp.size() != 0 ){
if(ret.size() != 0){
temp +=" ";
}
ret = temp + ret;
temp = "";
}
if(i == m -1 && temp.size() != 0) {
if(ret.size() != 0){
temp +=" ";
}
ret = temp + ret;
temp = "";
}
}
return ret;
}
};
代码2:ac
class Solution {
public:
void my_reverse(string& s, int begin, int end)
{
while(begin < end)
{
char temp = s[begin];
s[begin] = s[end];
s[end] = temp;
begin++; end--;
}
}
string reverseWords(string s) {
reverse(s.begin(), s.end());
while(s.size()){
if(s[s.size()-1] != ' ' && s[0] != ' ')
break;
if(s[s.size()-1] == ' ')
s.pop_back();
if(s[0] == ' ')
s.erase(0,1);
}
if(s.size() == 0) return s;
int m = s.size(), begin = 0, end = 0;
for(int i = 0; i < m; i++)
{
if(s[i] != ' '){
end++;
}
if(s[i] == ' ' || i == m-1){
if(begin == end){ // 出现连续的空格
s.erase(begin,1);
i--;m--;
} else { // 窗口中有数
my_reverse(s, begin, end-1);
begin = i+1; end = i+1;
}
}
}
return s;
}
};