leetcode-151-翻轉字符串裏的單詞
題目描述:
給定一個字符串,逐個翻轉字符串中的每個單詞。
示例:
輸入: "the sky is blue
",
輸出: "blue is sky the
".
說明:
- 無空格字符構成一個單詞。
- 輸入字符串可以在前面或者後面包含多余的空格,但是反轉後的字符不能包括。
- 如果兩個單詞間有多余的空格,將反轉後單詞間的空格減少到只含一個。
進階: 請選用C語言的用戶嘗試使用 O(1) 空間復雜度的原地解法。
要完成的函數:
void reverseWords(string &s)
說明:
1、這道題給定一個字符串s,相當於一個英文句子,要求把這個句子中的單詞反轉一下,後面的要放在前面,前面放在後面。
這個句子中可能會有多余的空格,可能會出現在第一個字符前面,可能出現在單詞之間,可能出現在最後一個字符後面。
你要將多余的空格去掉,最前面和最後面不能有空格,單詞之間的空格只能有一個。
c或c++語言用戶使用O(1)空間復雜度的原地解法,在字符串中修改,函數類型是void,不用返回。
2、這道題如果允許多定義一個新字符串(長度與給定字符串相同),那麽從給定字符串的後面讀起,讀出的字符從新的字符串的前面開始寫起。
在寫的過程中,調整新字符串的空格,使之符合要求,最後調用resize函數修改新字符串的長度,這道題也就解決了。
但現在要求原地解法,那麽只能逐個交換了,後面跟前面交換,這樣子換完之後,單詞內部順序也是反過來的,那再在單詞內部交換一下,也就ok了。
至於多余的空格問題,可以在交換之前,先解決掉這個問題,把後面的字符往前面移。
筆者的代碼思路如下,舉個例子,字符串是 "(兩個空格)the(三個空格)sky(兩個空格)is(一個空格)blue(兩個空格)":
1、先反轉整個字符串,變成(兩個空格)eulb(一個空格)si(兩個空格)yks(三個空格)eht(兩個空格)。
2、把後面的字符往前挪,去掉多余的空格,變成eulb(一個空格)si(一個空格)yks(一個空格)eht
3、在單詞內部進行反轉,變成blue(一個空格)is(一個空格)sky(一個空格)the。
所以具體代碼如下:(附詳解)
void reverseWords(string &s) { reverse(s.begin(),s.end());//先進行整個字符串的反轉 int i=0,j=0,start=0,t; while(i<s.size())//把字符往前挪,去掉多余的空格 { while(i<s.size())//找到第一個非空格字符 { if(s[i]!=‘ ‘) break; i++; } if(i==s.size())break;//如果找不到非空格字符,此時已經i==s.size(),所以直接結束這一部分的任務 j=i+1; while(j<=s.size())//找到i後面的第一個空格字符,位置記為j { if(s[j]==‘ ‘||s[j]==‘\0‘) break; j++; } while(i<j)//把i和j之間的字符往前挪,第一個就搬動到start這個位置,第二個搬動到start+1這個位置…… { s[start]=s[i]; start++; i++; } s[start]=‘ ‘;//搬完一個單詞之後,start現在這個位置變成空格字符 start++;//start到空格的下一位,作為新的單詞的起點 i++;//i退出循環時,i==j,現在i++,變成空格的下一位,繼續找下一個單詞的起點 } if(start==0)//邊界條件,如果結束了上述任務之後,start還是為0,說明根本就沒有非空格字符,那麽s變成空字符串 s=s.substr(0,0); else { s=s.substr(0,start-1);//去掉字符串後面多余的長度 i=0,j=1; while(i<s.size())//把每一個單詞反轉過來 { while(j<=s.size())//找到空格位置,記為j { if(s[j]==‘ ‘||s[j]==‘\0‘) break; j++; } t=j+1;//記下來,作為下一個單詞的起始位置 j--; while(i<j)//單詞內部反轉 { swap(s[i],s[j]); i++; j--; } i=t,j=i+1;//更新i和j的位置 } }
上述代碼實測4ms,beats 98.93% of cpp submissions。
leetcode-151-翻轉字符串裏的單詞