反向排列句子中的詞(Reverse Words in a String)

今天開始在https://oj.leetcode.com點擊打開鏈接上刷題,好囧啊~但是還是決定開始記錄刷題吧。也是大學裏沒做的,現在慢慢做!加油!!

題目:

Given an input string, reverse the string word by word.

For example, Given s = "the sky is blue", return "blue is sky the".

解題思路:

方案1.切分字符串獲得每個詞,不斷將字符串逆序拼接

void reverseWords(string &str) {
        const char * str_char = str.c_str();
        int len = str.length();
        string result = "";
       for(int i = 0; i < len; )
      {
          while(i < len && str_char[i] == ' ') i++;
          if(i == len) break;
          int start = i;
          while(i < len && str_char[i] != ' ') i++;;
          string temp = str.substr(start,i-start) +" "+ result;
          result = temp;
       }
       string ss(result.substr(0,result.length()-1));
       str = ss;
    }

解析:這個方案中使用了C++的substr函數,賦值指定位置和長度的字符串,核心思想爲string temp = str.substr(start,i-start) +" "+ result; result = temp;兩行代碼將word順序不斷逆序拼接。這種代碼結構簡潔,思路清晰,但是由於字符串拼接本身和substr函數本身很耗時的緣故,該方法看起來時間複雜度爲O(n),實際上耗時超過該值. Run time 44 ms.

方案2 將字符串整個逆轉過來,遇到空格作爲一個詞再次求逆

 void reverseWords(string &str) {
        int len = str.length();
        char *revers_str = new char[len+1];    //字符串逆序列

         const char* temparray = str.c_str();

         for(int i = 0 ; i < len; ++i)
        {
             revers_str[i] = temparray[ len - i -1];
        }
        revers_str[str.length()]='\0';
        int start = 0,index = 0;
        char *result = new char[len+1];
        while(start < len && revers_str[start] == ' ') start++;//去除起始的空格
        for(int i = start; i < len;)
        {
             int startindex = i; // 詞的起始位置
             while(i < len && revers_str[i] != ' ') i++;
             int endindex = i -1;//詞的終止位置
             for( int j = endindex; j >= startindex; j--)
                  result[index++] = revers_str[j];
   
             while(i < len && revers_str[i] == ' ' ) i++;//去除空格
             if( i < len ) result[index++]=' '; //word space
         }
         result[index]='\0';
         string ss(result);
         str = ss;
        delete revers_str, result;
    }

解析:這個方案中使用了C的c_str函數,獲取字符串的字符數組,用一個循環獲得逆序,之後順序讀取字符判斷,獲得每個詞的起始終止位置,再次逆序使得詞正確。這個方案雖然沒有字符串拼接,但是兩遍循環和字符逆序,相當於每次都要至少遍歷3次字符串,耗時也很長 Run time 40ms.

方案3 改進的逆序法,使用在逆序時就記錄詞的位置,可以在第二次掃描時直接加入空格成爲答案。

void reverseWords(string &str) {
        int len = str.length();
        char *revers_str = new char[len+1];
        int* space_indexs = new int[len+1];
        space_indexs[0] = 0;
        int word_num = 0, revers_len = 0;
        const char* temparray = str.c_str();
        for(int i = 0 ; i < len;)  //字符串求逆 並記錄space位置
       {
           while(i < len && temparray[ len - i -1] == ' ') i++;
           if(i == len) break;
           while(i < len && temparray[ len - i -1] != ' ')
           {
                 revers_str[revers_len++] = temparray[ len - i -1];
                 i++;
            }
            space_indexs[word_num++] = revers_len -1;
         }
         revers_str[revers_len]='\0';
    
         int result_len = 0;
         char *result = new char[len+1];
         for(int j =space_indexs[0]; j >=0 ; j--) //記錄第一個詞
             result[result_len++] = revers_str[j];
    
         for(int i = 1; i < word_num; i++) //記錄接下來的詞,每個詞前有space
        {
              result[result_len++] = ' ';
              for(int j = space_indexs[i]; j > space_indexs[i -1]; j-- )
                       result[result_len++] = revers_str[j];
        }
        result[result_len] = '\0';
        string ss(result);
        str = ss; //返回值

    }

解析:這個方案是三個方案中耗時最小的方案,通過一次遍歷記錄了每個詞的分割位置,並將字符序列求逆。但現在想想貌似直接記錄詞的位置第二次逆序讀取似乎可以更好。 Run time 12ms. 注意!!!我忘記delete了~

總結:

1. 關於格式,對空格要求比較多,所以輸出時要格外小心。關於Output Limited,使用了引用傳值,所以最後不用自己print,而是賦值回去。

2.關於RunTime Error,可能就是溢出,包括數組越界,遞歸棧溢出,數組下標爲負,除以0等。在第三個方案中我開始忘記了對space_index[0]的初始化,直接導致後來有可能使用到爲賦值的值,以後有東西了可以memset一下。開數組定義變量要想想不初始化的危險性。

3.關於new 和靜態數組,我一直喜歡new,delete,結果還是忘記delete。還有就是其實靜態數組在刷題和很多情況下都蠻有用的,省了很多new和delete的時間。有人提醒我說,全局的東西可以new,局部的就別再new了。

備註:由於還不會插入代碼,所以代碼格式是手動調的。。忍忍吧~~o(╯□╰)o

發佈了35 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章