1、问题描述:
Given an input string, reverse the string word by word.
For example,
Given s = "the sky is blue",
return "blue is sky the".
Clarification:
What constitutes a word?
A sequence of non-space characters constitutes a word.
一串非空字符组成单词
Could the input string contain leading or trailing spaces?
Yes. However, your reversed string should not contain leading or trailing spaces.
输入字符串的首尾都可能包含空格,但是翻转后的字符串不要有
How about multiple spaces between two words?
Reduce them to a single space in the reversed string.
应该处理两单词间连续多个空格的情况,使其只包含一个
2、问题求解:
方法一:O(n)时间,并且需要辅助空间O(n)
class Solution {
public:
void reverseWords(string &s) {//如s为“the sky”
int n=s.size();
int i=n-1;
//辅助字符串存放结果字符串
string stmp="";//最后为“sky the”
while(i >= 0)
{
while(s[i]==' ' && i>=0)
{//(1)处理连续有多个空格的情况
i--;
}
if(i<0) break;//s处理完空格,若后续没有单词则应跳出循环
string wordtmp="";
for(;i>=0 && s[i]!=' ';i--)
{//(2)从后往前遍历,每次取得一个单词赋给wordtmp
wordtmp += s[i];
}//第一个单词为yks
//(3)翻转wordtmp,如yks
reverse(wordtmp.begin(), wordtmp.end());
if(stmp != "")
{//(4)在将翻转后的单词加入到stmp之前先加入空格(若非首单词)
stmp.append(" ");
}
stmp.append(wordtmp);//(5)加入到stmp
}
s=stmp;
}
};
方法二:O(n)时间,不需要辅助空间
(1)从前往后遍历,依次翻转每个单词
(2)翻转整个字符串
class Solution {
public:
void reverseWords(string &s) {
int n=s.size();
int i=0, j=0;
int start=0;
while(i<n)
{
while(i<n && s[i]==' ') i++;//(1)处理空格
if(i<n && j>0)
{//(2)如果处理到非首单词(j>0),要在其前加入空格
s[j++]=' ';
}
//(3)翻转每个单词
start=j;
while(i<n && s[i]!=' ')
{
s[j++]=s[i++];
}
reverse(s.begin()+start, s.begin()+j);
}
s.resize(j);//(4)重置s大小
reverse(s.begin(), s.end());//(5)翻转整个字符串
}
};
3、扩展:
对于一个给定的字符串,我们需要在线性(也就是O(n))的时间里对它做一些变形。首先这个字符串中包含着一些空格,就像”Hello World”一样,然后我们要做的是把着个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。比如”Hello World”变形后就变成了”wORLD hELLO”。
分析:该题与上题的区别是不丢弃字符串前后的空格,只不过翻转后后边的空格放到前面,而前面的空格放到后面;再就是单词大小写转换。
#include <iostream>
#include<string.h>
#include<algorithm>
using namespace std;
class Transform {
public:
string trans(string s, int n) {
int i=n-1;
//辅助字符串存放结果字符串
string stmp="";//最后为“sky the”
while(i >= 0)
{//从后往前
while(s[i]==' ' && i>=0)
{//(1)见到空格就放入stmp(后面的空格最终放到前面,单词之间的空格也会放入)
stmp.append(" ");//!!!
i--;
}
//if(i<0) break;//s处理完空格,若后续没有单词则应跳出循环
string wordtmp="";
for(;i>=0 && s[i]!=' ';i--)
{//(2)从后往前遍历,每次取得一个单词赋给wordtmp
wordtmp += s[i];
}//第一个单词为yks
//(3)翻转wordtmp,如yks
reverse(wordtmp.begin(), wordtmp.end());
/*
if(stmp.find_first_not_of(" ")!=string::npos || stmp!="")
{//(4)在将翻转后的单词加入到stmp之前先加入空格(若非首单词)
stmp.append(" ");
}*/
stmp.append(wordtmp);//(5)加入到stmp
}
s=stmp;
cout<<s<<" "<<s.size()<<endl;
//(4)下边用于转换大小写
i=0;
while(i<n)
{
if(s[i]==' ') i++;
else
{
s[i]=isupper(s[i])?tolower(s[i]):toupper(s[i]);
i++;
}
}
return s;
}
};
int main()
{
Transform t;
string str=" We are champion";
//string str1=" h i";
int n=str.size();
cout<<n<<endl;
string res=t.trans(str, n);
cout<<res<<endl;
return 0;
}
结果:
17
champion are We 17
CHAMPION ARE wE
Process returned 0 (0x0) execution time : 2.889 s
Press any key to continue.
即翻转后字符串大小不变。
若输入" We are champion",则输出"CHAMPION ARE wE ".