題目如下:
Given an input string, reverse the string word by word.
For example,
Given s = "the sky is blue
",
return "blue is sky the
".
- 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.
這道題目難度不是很大,但是坑比較多,一個是首尾的空字符要處理掉,另一個是中間間隔的空字符可能不是一個字符,另外是否有用‘\t'或其他的作爲間隔符沒有仔細考證,如果單詞之間有多個空格的話,也要把他們縮減爲一個空格。
如果有split函數的話,就比較好解決。
乍一看,想到一個思路:可以用一個棧來保存每個單詞,由於棧有後進先出的性質,出棧後的順序剛好逆序,符合題目的要求。
class Solution {
public:
void reverseWords(string &s) {
stack<string> stk;
string wrd = "";
int pre = -1, cnt = -1, i = 0;
for(i = 0; i < s.length(); ++i)
{
if(s[i] == ' ' || s[i] == '\r' || s[i] == '\t' || s[i] == '\n')
{
if(pre >= 0 && cnt > 0){
wrd = s.substr(pre, cnt);
stk.push(wrd);
}
pre = -1;
cnt = -1;
}else{
if(cnt == -1 && pre == -1)
{
cnt = 1;
pre = i;
}else
++cnt;
}
}
if(pre >= 0 && cnt > 0)
{
wrd = s.substr(pre, cnt);
stk.push(wrd);
}
string ret = "";
int first = 1;
while(!stk.empty())
{
wrd = stk.top();
stk.pop();
if(first == 1){
ret += wrd;
first = 0;
}else
ret += " " + wrd;
}
s = ret;
}
};
這段代碼比較長,主要是用pre記錄第一個非空格的字符,用cnt記錄單詞的長度,每找到一個單詞就放入棧,找完以後再出棧存到字符串中即可。
隔了一段時間之後,我又寫下了另外一種解法:用兩個位置變量pre和p分別記錄單詞兩段空格的位置,這樣用substr就能提取單詞。然後直接逆序放到另一個字符串保存。
class Solution {
public:
void reverseWords(string &s) {
size_t pre = -1, p;
while((pre+1) < s.length() && (s[pre+1] == ' ' || s[pre+1] == '\t'))++pre;
p = pre + 1;
string ss = s;
s = "";
int flag = 1;
while(p < ss.length()){
while(p < ss.length() && ss[p] != ' ' && ss[p] != '\t')++p;
if(flag == 0){
s = ss.substr(pre+1, p-pre-1) + " " + s;
}else{
s = ss.substr(pre+1, p-pre-1);
flag = 0;
}
pre = p;
while((pre+1) < ss.length() && (ss[pre+1] == ' ' || ss[pre+1] == '\t'))++pre;
p = pre+1;
}
}
};
這裏要注意的是,結果如果只有一個單詞的話,就不要空格字符串。兩個單詞之間才需要一個空格。另外首尾的空格也要處理。
上面的代碼還是稍微有點長,下面有個更加簡化的版本:
class Solution {
public:
void reverseWords(string &s) {
string b = "", t = "";
size_t j = 0;
while(j < s.length() && (s[j] == ' ' || s[j] == '\t')) ++j;
while(j < s.length()){
while(j < s.length() && s[j] != ' ' && s[j] != '\t')t += s[j++];
b = t + " " + b;
t = "";
while(j < s.length() && (s[j] == ' ' || s[j] == '\t'))++j;
}
s = b.substr(0, b.length()-1);
}
};
第一個while循環處理開頭的空字符,每個單詞後面都帶上一個空格,最後返回結果的時候把最後一個單詞後面的空格去掉就可以。
寫這段代碼的時候遇到一個坑:size_t是無符號的類型,我開始將一個變量賦值爲-1,導致變量的值被轉化爲整數,以至於最後的結果很奇怪,不注意的話也是比較難看出來的。