[題解]劍指 Offer 58 - I. 翻轉單詞順序(C++)
阿新 • • 發佈:2021-08-23
題目
輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。為簡單起見,標點符號和普通字母一樣處理。例如輸入字串"I am a student. ",則輸出"student. a am I"。
示例 1:
輸入: "the sky is blue"
輸出:"blue is sky the"
示例 2:
輸入: " hello world! "
輸出:"world! hello"
解釋: 輸入字串可以在前面或者後面包含多餘的空格,但是反轉後的字元不能包括。
示例 3:
輸入: "a good example" 輸出:"example good a" 解釋: 如果兩個單詞間有多餘的空格,將反轉後單詞間的空格減少到只含一個。
說明:
- 無空格字元構成一個單詞。
- 輸入字串可以在前面或者後面包含多餘的空格,但是反轉後的字元不能包括。
- 如果兩個單詞間有多餘的空格,將反轉後單詞間的空格減少到只含一個。
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
思路
要翻轉單詞的順序同時保持單詞內字元的順序,很自然地想到利用棧先進後出的特性。遍歷s把單詞逐個入棧,然後丟擲單詞直到棧空,記得在首個單詞以外的單詞前面加上空格。
時間複雜度O(n),空間複雜度O(n)。
程式碼
class Solution { public: string reverseWords(string s) { stack<string> stk; for(int left = 0; left < s.size(); ++left) { if(s[left] != ' ') { int right = left; while(right < s.size() && s[right] != ' ') right++; string tmp(s.begin() + left, s.begin() + right); stk.push(tmp); left = right; } } string ans = ""; while(!stk.empty()) { if(!ans.empty()) ans += ' '; ans += stk.top(); stk.pop(); } return ans; } };
改進
用棧解決需要額外O(n)的空間,能不能直接在傳入的s上原地修改?利用c++的翻轉函式reverse(也可以自己實現)可以做到,先翻轉整個字串,然後用雙指標,write指向要寫入的位置,read指向讀到單詞的位置;read讀到單詞時,用wordend向後遍歷到空格或者字串結束,把wordend遍歷到的字元寫到write指向的位置,然後再在新字串離翻轉新寫進來的這個單詞。注意每次寫入單詞前除了首個單詞外要加上空格。
時間複雜度O(n),空間複雜度O(1)。
程式碼
class Solution {
public:
string reverseWords(string s) {
reverse(s.begin(), s.end());
int write = 0, n = s.size();
for(int read = 0; read < n; ++read)
{
if(s[read] != ' ')
{
if(write != 0) s[write++] = ' ';
int wordend = read;
while(wordend < n && s[wordend] != ' ') s[write++] = s[wordend++];
reverse(s.begin() + write - (wordend - read), s.begin() + write);
read = wordend;
}
}
s.erase(s.begin() + write, s.end());
return s;
}
};