Django-ORM-多表操作
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。為簡單起見,標點符號和普通字母一樣處理。例如輸入字串"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"
解釋: 如果兩個單詞間有多餘的空格,將反轉後單詞間的空格減少到只含一個。
說明:
無空格字元構成一個單詞。
輸入字串可以在前面或者後面包含多餘的空格,但是反轉後的字元不能包括。
如果兩個單詞間有多餘的空格,將反轉後單詞間的空格減少到只含一個。
注意:本題與主站 151 題相同:https://leetcode-cn.com/problems/reverse-words-in-a-string/
注意:此題對比原題有改動
解法1:
笨蛋解法——先另外寫一個去空格函式去掉string首尾的空格,再從頭開始用迴圈每次擷取第一個單詞進棧,儲存截剩下的字串並再次去除首尾空格(防止單詞與單詞間有多個空格),之後再從剩下的字串擷取單詞,如此迴圈往復直至最後。
迴圈結束後,棧中所有單詞出棧並以空格拼接起來即是題目所要求的順序。
class Solution { public: string reverseWords(string s) { trim(s); if(s.empty()) //特殊情況 return s; stack<string> S; int n = s.find(' '); string piece = s.substr(0,n), remain = s.substr(n+1); if(remain.at(0) == ' ') //去首尾空格 trim(remain); while(n != string::npos) //擷取單詞 { S.push(piece); // cout<<"S.top:"<<S.top()<<"\tremain:"<<remain<<endl; if(remain.at(0) == ' ') trim(remain); n = remain.find(' '); piece = remain.substr(0,n); remain = remain.substr(n+1); } S.push(remain); //找不到空格了,直接入棧 s.clear(); //原字串清空 while(!S.empty()) //出棧,拼接單詞 { bool last_empty = false; s.append(S.top()); s.append(" "); S.pop(); } while(s.at(s.size() - 1) == ' ') s.pop_back(); return s; } void trim(string &s) //去字串首尾空格 { if( !s.empty() ) { s.erase(0,s.find_first_not_of(" ")); s.erase(s.find_last_not_of(" ") + 1); } } };
此演算法未經深思熟慮,時空複雜度均表現不佳,尤其空間複雜度是其他演算法的8-10倍。
解法2:
從後向前遍歷,用倆索引i,j標出單詞並拼接。
1 class Solution { 2 public: 3 string reverseWords(string s) { 4 if (s.empty()) 5 return s; 6 string res = ""; 7 int i = s.size() - 1; //i從字串最後開始 8 while (i >= 0){ 9 while (i >= 0 && s.at(i) == ' ') 10 --i; 11 int j = i; //j為當前指向單詞的最後一個字母 12 while (i >= 0 && s.at(i) != ' '){ 13 --i; 14 } //i為當前指向單詞前的第一個空格 15 if (i < j){ //只要還有單詞 16 res += s.substr(i + 1, j - i);//就拼接 17 res += " "; 18 } 19 } 20 return res.substr(0, res.size() - 1); //去最後的空格 21 } 22 23 24 };
空間佔用相比上個演算法大大改善,時間上若是可以把字串拼接中的+改為string類的方法append會更快。
方法3:
與演算法1想法類似,但空間佔用大大改善。
1 class Solution { 2 public: 3 string reverseWords(string s) { 4 stack<string>sta;//利用棧實現倒裝string 以空格為界限分割每個單詞 每個單詞作為stack的元素壓棧 5 int len = s.size(); 6 for(int i = 0;i < len;++i) 7 { 8 string s1;//一個單詞 單詞以空格分割 9 while(i < len && !isblank(s[i])) 10 { 11 s1 += s[i]; 12 ++i; 13 } 14 if(!s1.empty()) 15 sta.push(s1); 16 } 17 string s2 = ""; 18 while(!sta.empty()) 19 { 20 s2 += sta.top(); 21 sta.pop(); 22 if(!sta.empty()) 23 s2 += " "; 24 } 25 return s2; 26 } 27 };
方法4:
換python一行解決。
1 class Solution: 2 def reverseWords(self, s: str) -> str: 3 return " ".join(s.split()[::-1])
然而看著雖然爽,時間佔用上是演算法1的5倍,空間佔用上是演算法2、3的2倍。
方法5:
利用istream類去空格的特性,藉助棧完成目標。
1 class Solution { 2 public: 3 string reverseWords(string s) { 4 stack<string> stack1; 5 istringstream input(s); 6 string t; 7 string res; 8 while(input>>t)stack1.push(t);//每遇到一個空格就迴圈一次直到結尾 9 while(!stack1.empty()){ 10 res.append(stack1.top()); 11 res.append(" "); 12 stack1.pop(); 13 } 14 if(res.length()==0)return res; 15 res.pop_back(); //去最後的空格 16 return res; 17 } 18 };
此法在時間空間複雜度均一般,時間複雜度與演算法1、2、3持平,空間複雜度與演算法2、3持平。
方法6:
1 class Solution { 2 public: 3 string reverseWords(string s) { 4 stack<char> word; 5 string result = ""; 6 for (int i = s.size() - 1; i >= 0; --i) 7 { 8 if (s[i] != ' ') //遇到單詞則入棧 9 { 10 word.push(s[i]); 11 } 12 if (s[i] == ' ' || i == 0) //遇到空格或第一個字元都要檢查一下棧中是否有單詞可以彈出 13 { 14 bool flag = false; //標記是否發生出棧 15 while (word.empty() == false) 16 { 17 result.push_back(word.top()); //因為word棧儲存的元素為char型,而result為string型,故不能相加,只能使用push_back() 18 word.pop(); 19 flag = true; 20 } 21 if (flag) 22 { 23 result += " "; 24 } 25 } 26 } 27 return result.substr(0, result.size() - 1); //最後一個單詞後面會多加一個空格 28 } 29 }; 30 31 // 作者:wade-d 32 // 連結:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/solution/151-fan-zhuan-zi-fu-chuan-li-de-dan-ci-y-hn6y/ 33 // 來源:力扣(LeetCode) 34 // 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
用字母棧,從後向前遍歷,遇字母則入,遇空格全部彈出,至開頭全部彈出。
此法用時與記憶體消耗方面均表現優異。