(迴文串)leetcode各種迴文串問題

Kobe10發表於2017-02-04
  • 題目一:最長連續迴文子串。
    •   問題分析:迴文串顧名思義表示前後讀起來都是一樣,這裡面又是需要連續的。分析這個問題的結構,可以想到多種方法。暴力解決的方式,2層迴圈遍歷得出各個子串,然後再去判斷該子串是否迴文,這樣的話O(N)=n的三次方,還有一種是dp解決。

    •   解題方法一:暴力解決的方法。前面已經講到了方法,下面給出方法的實現。
      class Solution {
      public:
          string longestPalindrome(string s) {
              int maxlength = 0;
              int start = 0, end = 0;
              for (int i=0; i<s.size(); i++){
                  for (int j=i+1; j<s.size(); j++){
                      int temp1, temp2;
                      for (temp1=i, temp2=j; temp1<temp2; temp1++, temp2--){
                          if (s[temp1] != s[temp2])
                              break;
                      }
                      if (temp1>=temp2 && j-i>maxlength){
                          maxlength = j-i+1;
                          start = i;
                          end = j;
                      }
                  }
              }
              if (maxlength > 0)
                  s.substr(start, maxlength);
              return NULL;
          }
          
      };
    •   解題方法二:DP求解。為什麼會想到dp求解呢。首先分析問題。最長連續子串是否迴文。如果一個子串迴文,那麼子串的子串也就是迴文的,依次類推就簡化為一個小的解,從而得到整體的解。
           具體思路:設定一個int二維陣列DP[i][j]用來儲存從i到j的串是否迴文,1表示是,0表示否。
                         這裡有三種情況需要考慮:①:當只有一個字元的時候,i=j,肯定迴文   DP[i][j] = 1;
                                                       ②:當兩個兩個字元相鄰的時候,如果他們相等,那麼他們也是迴文的,i-j<2 && s[i]==s[j]  -> DP[i][j] = 1
                                                          ③:當超過兩個字元的時候,如果他們首尾是相同的並且除去首尾字元的剩餘字元也是迴文的話,那麼這個串也是迴文的。
                                                                s[i] == s[j] && DP[i+1][j-1] = 1  ->DP[i][j] = 1
                         考慮完這三種情況,就設定兩個指標記錄最長迴文子串的左右位置,然後直接提取出來即可。DP[i][j] = 1 並且最長字元長度小於當前字元長度。
    • class Solution {
      public:
          string longestPalindrome(string s) {
              int dp[s.size()][s.size()] ;
              int left = 0, right = 0, maxlength = 0;
              for (int i=0; i<s.size(); i++){
                  for (int j=0; j<i; j++){
                  //這裡表示出了所有的情況
                  //當為相鄰兩個字串時,如果相等則為1,當大於兩個字串時,如果首尾相同並且子串是迴文的話,那麼這個串也是迴文
                      dp[j][i] = (s[i] == s[j] && ((i-j < 2) || dp[j+1][i-1]));
                      if (dp[j][i] && maxlength< i-j+1) {
                          maxlength = j-i+1;
                          left = j;
                          right = i;
                      }
                  }
                  dp[i][i] = 1;//這裡表示單個字串就是迴文串。 
              }
              return s.substr(left, right-left+1);
          }
      };



  • 題目二:給出一個整數,判斷這個整數是否是迴文數字,不能使用額外的儲存空間,意思是不能將他變為字串。

    •   題目分析:第一想到的就是將他變成一個字串然後對他進行判斷是否是迴文串。但是題目不能變為字串。這裡我們就可以變換一種方法。比如對數字“12321”,12321/10000=1,首位為1, 12321%10=1,尾部為1,然後繼續判斷232這個數字,按照相同的方法(這裡的關鍵是剩餘數字的位數需要確定)

    • 程式碼:
      class Solution {
      public:
          bool isPalindrome(int x) {
              if (x < 0)
                  return false;
              int flag = 1;
              while(x/flag >= 10){//求整數的最高位   -》這是求最高位的位數的技巧
                  flag *= 10;
              }
              while (x) {
                  int left = -1, right = -1;
                  left = x/flag;
                  right = x%10;
                  if (left != right)
                      return false;
                  x = (x%flag)/10;
                  flag = flag/100;
              }
              return true;
          }
      };

       

  • 題目三:判斷一個字串是否是迴文,只考慮字母和數字,其他空格之類的忽略。

    •   思路:這個就是簡答的判斷字串是否是迴文的情況。碰到不是字母或者是數字的情況直接跳轉到下一個字串,頭尾依次進行比較。這裡需要考慮大小寫的問題,所以比較是否相同直接利用assic的值進行比較比較合適。s[left] +32 -'a')%32 !=  (s[right] +32 -'a')%32  ->>這裡%32表示大小寫的assic 32是一個迴圈。

    • 程式碼
      class Solution {
      public:
          bool isPalindrome(string s) {
              int len = s.size();
              int left = 0, right = len-1;
              while (left < right){
                  if (!isAlphaNum(s[left]))
                      left++;
                  else if (!isAlphaNum(s[right]))
                      right--;
                  else if((s[left] +32 -'a')%32 !=  (s[right] +32 -'a')%32)
                      return false;//這裡考慮到大小寫,所以直接這樣用assic進行比較
                  else{
                      left++,right--;
                  }
              }
              return true;
          }
          bool isAlphaNum(char &ch) {
              if (ch >= 'a' && ch <= 'z') return true;
              if (ch >= 'A' && ch <= 'Z') return true;
              if (ch >= '0' && ch <= '9') return true;
              return false;
          }
      };
  • 題目四:
    給定一個字串s,分割槽s使得分割槽的每個子字串是一個迴文。
    
    返回s的所有可能的迴文分割槽。
    
    例如,給定s =“aab”,
    返回
    
       [
         [“aa”,“b”],
         [“a”,“a”,“b”]
       ]]

    •   題目分析:實際上這道題目是一道組合的題目,對付組合的題目,回溯法是一個很好的方法。這裡是要拆分字串(拆分的串都是迴文串),得出所有的拆分情況。組合問題->回溯法,DFS演算法很好的解決了這個問題。先是針對一個一個字元進行拆分,然後是針對兩個字元是迴文串的串,之後是含有三個字元是迴文串的字元,依次類推(這裡需要一個函式是判斷該字串是否為迴文的函式,給定首尾進行判斷)。dfs遞迴的條件是找到符合要求的迴文串,然後對後面的串也進行遞迴的求解(從頭開始繼續進行遞迴求解)
    •   例項分析:
      a b c e e  -> 第一組:a 迴文  a進temp, b迴文 b進temp, c 迴文 c進temp  , e 迴文 e進temp ,  e 迴文 e進temp找到一組,出容器。
                         第二組:回溯,回溯到第一個e,進行兩個字元迴文查詢判斷,找到ee,之後就沒有了。

    • 程式碼:
      class Solution {
      public:
          vector<vector<string>> partition(string s) {
              vector<vector<string> > res;
              vector<string> temp;
              partition(s, 0, temp, res);
              return res;
          }
          void partition(string &s, int start, vector<string> temp, vector<vector<string> > &res){
              int len = s.size();
              if (start == len)
                  res.push_back(temp);
              for (int i=start; i<len; i++){
                  if (isPalindromeStr(s, start, i)){
                      temp.push_back(s.substr(start, i-start+1));
                      partition(s, i+1, temp, res);
                      temp.pop_back();
                  }
              }
          }
          bool isPalindromeStr(string s, int start, int end){
              while (start < end){
                  if (s[start] != s[end]){
                      return false;
                  }else
                      start++,end--;
              } 
              return true;
          }
      };

       

相關文章