1. 程式人生 > 其它 >Django-ORM-多表操作

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 // 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

用字母棧,從後向前遍歷,遇字母則入,遇空格全部彈出,至開頭全部彈出。
此法用時與記憶體消耗方面均表現優異。