【解题思路】
在不使用额外空间的前提下,先将多余的空格移除,包括单词之间的和整个字符串首尾处的,(单词与单词之间只需要一个空格来分割,即两个空格不可以是前后关系)然后将整个字符串反转,最后将每个单词逐个反转,还要将空格添加回去。
移除空格的函数,写的思路:遍历整个字符串,每次移动指针i++,就执行一次判断,只要遍历到的s[i]不是空格,就表明还在一个单词内,将这个地址中的元素用s[slow]来记录,其实还是在s这个字‘字符型数组’内,只不过用了不同的指针变量名(索引名)来进行标记,同时里面的字母顺序和空格数也发生了变化。
void removeExtraSpaces(string& s){
int slow = 0;
for(int i = 0;i<s.size();++i){
if(s[i] != ' '){ //遍历不是空格的位置
if(slow != 0)s[slow++] = ' '; //判断该单词不是第一个单词,给单词之间添加空格
while(i < s.size()&&s[i] != ' '){//只要没到末尾就将单词继续添加进去
s[slow++] = s[i++];
}
}
}
s.resize(slow);
}
反转字符串s
void reverse(string& s,int start, int end){
for(int i = start, j = end;i < j; i++,j--){//使用双指针将字符串s反转
swap(s[i],s[j]);
}
}
主要的函数代码:
……
string reverseWords(string s) {
removeExtraSpaces(s); //先把多余的空格去除
reverse(s,0,s.size()-1);//反转字符串
int start = 0;//去除空格后,保证第一个单词的下标为0
for(int i = 0;i <= s.size();++i){
if(i == s.size() || s[i] == ' '){//到达i加到s.size(),且为空格,表明到当前单词的最后了,此时进行对单词进行翻转
reverse(s,start,i-1);
start = i + 1;,更新到字符串的下一位,即下一个单词的开始地址
}
}
return s;
}
};
完整求解代码:
class Solution {
public:
void reverse(string& s,int start, int end){
for(int i = start, j = end;i < j; i++,j--){
swap(s[i],s[j]);
}
}
void removeExtraSpaces(string& s){
int slow = 0;
for(int i = 0;i<s.size();++i){
if(s[i] != ' '){
if(slow !=0)s[slow++] = ' ';
while(i < s.size()&&s[i] != ' '){
s[slow++] = s[i++];
}
}
}
s.resize(slow);
}
string reverseWords(string s) {
removeExtraSpaces(s);
reverse(s,0,s.size()-1);
int start = 0;
for(int i = 0;i <= s.size();++i){
if(i == s.size() || s[i] == ' '){
reverse(s,start,i-1);
start = i + 1;
}
}
return s;
}
};