LeetCode:Palindrome Partitioning

系统 1841 0

LeetCode:Palindrome Partitioning

题目如下:(把一个字符串划分成几个回文子串,枚举所有可能的划分)

Given a string  s , partition  s  such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of  s .

For example, given  s  =  "aab" ,
Return

[ ["aa","b"], ["a","a","b"] ]

 

分析 :首先对字符串的所有子串判断是否是回文,设f[i][j] = true表示以i为起点,长度为j的子串是回文,等于false表示不是回文,那么求f[i][j]的动态规划方程如下:

  • 当j = 1,f[i][j] = true;

  • 当j = 2,f[i][j] = (s[i]==s[i+1]),其中s是输入字符串

  • 当j > 2, f[i][j] = f[i+1][j-2] && (s[i] == s[i+j-1])(即判断s[m..n]是否是回文时:只要s[m+1...n-1]是回文并且s[m] = s[n],那么它就是回文,否则不是回文)

这一题也可以不用动态规划来求f,可以用普通的判断回文的方式判断每个子串是否为回文。                                                                                                                本文地址

求得f后,根据 f 可以构建一棵树,可以通过DFS来枚举所有的分割方式,代码如下:

        
           1
        
        
          class
        
        
           Solution {


        
        
           2
        
        
          public
        
        
          :


        
        
           3
        
             vector<vector<
        
          string
        
        >> partition(
        
          string
        
        
           s) {


        
        
           4
        
        
          //
        
        
           IMPORTANT: Please reset any member data you declared, as


        
        
           5
        
        
          //
        
        
           the same Solution instance will be reused for each test case.
        
        
           6
        
                 vector< vector<
        
          string
        
        > >
        
          res;


        
        
           7
        
        
          int
        
         len =
        
           s.length();


        
        
           8
        
        
          if
        
        (len == 
        
          0
        
        )
        
          return
        
        
           res;


        
        
           9
        
        
          //
        
        
          f[i][j] = true表示以i为起点,长度为j的子串是回文
        
        
          10
        
        
          bool
        
         **f = 
        
          new
        
        
          bool
        
        *
        
          [len];


        
        
          11
        
        
          for
        
        (
        
          int
        
         i = 
        
          0
        
         ; i < len; i++
        
          )


        
        
          12
        
        
                  {


        
        
          13
        
                     f[i] = 
        
          new
        
        
          bool
        
        [len+
        
          1
        
        
          ];


        
        
          14
        
        
          for
        
        (
        
          int
        
         j = 
        
          0
        
        ; j < len+
        
          1
        
        ; j++
        
          )


        
        
          15
        
                         f[i][j] = 
        
          0
        
        
          ;


        
        
          16
        
                     f[i][
        
          1
        
        ] = 
        
          true
        
        
          ;


        
        
          17
        
        
                  }


        
        
          18
        
        
          for
        
        (
        
          int
        
         k = 
        
          2
        
        ; k <= len; k++
        
          )


        
        
          19
        
        
                  {


        
        
          20
        
        
          for
        
        (
        
          int
        
         i = 
        
          0
        
        ; i <= len-k; i++
        
          )


        
        
          21
        
        
                      {


        
        
          22
        
        
          if
        
        (k == 
        
          2
        
        )f[i][
        
          2
        
        ] = (s[i] == s[i+
        
          1
        
        
          ]);


        
        
          23
        
        
          else
        
         f[i][k] = f[i+
        
          1
        
        ][k-
        
          2
        
        ] && (s[i] == s[i+k-
        
          1
        
        
          ]);


        
        
          24
        
        
                      }


        
        
          25
        
        
                  }


        
        
          26
        
                 vector<
        
          string
        
        >
        
           tmp;


        
        
          27
        
                 DFSRecur(s, f, 
        
          0
        
        
          , res, tmp);


        
        
          28
        
        
          for
        
        (
        
          int
        
         i = 
        
          0
        
         ; i < len; i++
        
          )


        
        
          29
        
        
                      delete [](f[i]);


        
        
          30
        
        
                  delete []f;


        
        
          31
        
        
          return
        
        
           res;


        
        
          32
        
        
              }


        
        
          33
        
        
          34
        
        
          void
        
         DFSRecur(
        
          const
        
        
          string
        
         &s, 
        
          bool
        
         **f, 
        
          int
        
        
           i, 


        
        
          35
        
                     vector< vector<
        
          string
        
        > > &res, vector<
        
          string
        
        > &
        
          tmp)


        
        
          36
        
             {
        
          //
        
        
          i为遍历的起点
        
        
          37
        
        
          int
        
         len =
        
           s.length();


        
        
          38
        
        
          if
        
        (i >= len){res.push_back(tmp); 
        
          return
        
        
          ;}


        
        
          39
        
        
          for
        
        (
        
          int
        
         k = 
        
          1
        
        ; k <= len - i; k++
        
          )


        
        
          40
        
        
          if
        
        (f[i][k] == 
        
          true
        
        
          )


        
        
          41
        
        
                      {


        
        
          42
        
        
                          tmp.push_back(s.substr(i, k));


        
        
          43
        
                         DFSRecur(s, f, i+
        
          k, res, tmp);


        
        
          44
        
        
                          tmp.pop_back();


        
        
          45
        
        
                      }


        
        
          46
        
        
          47
        
        
              }


        
        
          48
        
         };
      

LeetCdoe:Palindrome Partitioning II

题目如下:(在上一题的基础上,找出最小划分次数)

Given a string  s , partition  s  such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of  s .

For example, given  s  =  "aab" ,
Return  1  since the palindrome partitioning  ["aa","b"]  could be produced using 1 cut.                                                                                                           本文地址

算法1 :在上一题的基础上,我们很容易想到的是在DFS时,求得树的最小深度即可(遍历时可以根据当前求得的深度进行剪枝),但是可能是递归层数太多,大数据时运行超时,也贴上代码:

  View Code

算法2 :设f[i][j]是i为起点,长度为j的子串的最小分割次数,f[i][j] = 0时,该子串是回文,f的动态规划方程是:

f[i][j] = min{f[i][k] + f[i+k][j-k] +1} ,其中 1<= k <j

这里f充当了两个角色,一是记录子串是否是回文,二是记录子串的最小分割次数,可以结合上一题的动态规划方程,算法复杂度是O(n^3), 还是大数据超时,代码如下:

  View Code

算法3 :同上一题,用f来记录子串是否是回文,另外优化最小分割次数的动态规划方程如下,mins[i] 表示子串s[0...i]的最小分割次数:

  • 如果s[0...i]是回文,mins[i] = 0
  • 如果s[0...i]不是回文,mins[i] = min{mins[k] +1 (s[k+1...i]是回文)  或  mins[k] + i-k  (s[k+1...i]不是回文)} ,其中0<= k < i

代码如下,大数据顺利通过,结果Accept:                                                                                                                                  本文地址

        
           1
        
        
          class
        
        
           Solution {


        
        
           2
        
        
          public
        
        
          :


        
        
           3
        
        
          int
        
         minCut(
        
          string
        
        
           s) {


        
        
           4
        
        
          //
        
        
           IMPORTANT: Please reset any member data you declared, as


        
        
           5
        
        
          //
        
        
           the same Solution instance will be reused for each test case.
        
        
           6
        
        
          int
        
         len =
        
           s.length();


        
        
           7
        
        
          if
        
        (len <= 
        
          1
        
        )
        
          return
        
        
          0
        
        
          ;


        
        
           8
        
        
          //
        
        
          f[i][j] = true表示以i为起点,长度为j的子串是回文
        
        
           9
        
        
          bool
        
         **f = 
        
          new
        
        
          bool
        
        *
        
          [len];


        
        
          10
        
        
          for
        
        (
        
          int
        
         i = 
        
          0
        
         ; i < len; i++
        
          )


        
        
          11
        
        
                  {


        
        
          12
        
                     f[i] = 
        
          new
        
        
          bool
        
        [len+
        
          1
        
        
          ];


        
        
          13
        
        
          for
        
        (
        
          int
        
         j = 
        
          0
        
        ; j < len+
        
          1
        
        ; j++
        
          )


        
        
          14
        
                         f[i][j] = 
        
          false
        
        
          ;


        
        
          15
        
                     f[i][
        
          1
        
        ] = 
        
          true
        
        
          ;


        
        
          16
        
        
                  }


        
        
          17
        
        
          int
        
         mins[len];
        
          //
        
        
          mins[i]表示s[0...i]的最小分割次数
        
        
          18
        
                 mins[
        
          0
        
        ] = 
        
          0
        
        
          ;


        
        
          19
        
        
          for
        
        (
        
          int
        
         k = 
        
          2
        
        ; k <= len; k++
        
          )


        
        
          20
        
        
                  {


        
        
          21
        
        
          for
        
        (
        
          int
        
         i = 
        
          0
        
        ; i <= len-k; i++
        
          )


        
        
          22
        
        
                      {


        
        
          23
        
        
          if
        
        (k == 
        
          2
        
        )f[i][
        
          2
        
        ] = (s[i] == s[i+
        
          1
        
        
          ]);


        
        
          24
        
        
          else
        
         f[i][k] = f[i+
        
          1
        
        ][k-
        
          2
        
        ] && (s[i] == s[i+k-
        
          1
        
        
          ]);


        
        
          25
        
        
                      }


        
        
          26
        
        
          if
        
        (f[
        
          0
        
        ][k] == 
        
          true
        
        ){mins[k-
        
          1
        
        ] = 
        
          0
        
        ; 
        
          continue
        
        
          ;}


        
        
          27
        
                     mins[k-
        
          1
        
        ] = len - 
        
          1
        
        
          ;


        
        
          28
        
        
          for
        
        (
        
          int
        
         i = 
        
          0
        
        ; i < k-
        
          1
        
        ; i++
        
          )


        
        
          29
        
        
                      {


        
        
          30
        
        
          int
        
        
           tmp;


        
        
          31
        
        
          if
        
        (f[i+
        
          1
        
        ][k-i-
        
          1
        
        ] == 
        
          true
        
        )tmp = mins[i]+
        
          1
        
        
          ;


        
        
          32
        
        
          else
        
         tmp = mins[i]+k-i-
        
          1
        
        
          ;


        
        
          33
        
        
          if
        
        (mins[k-
        
          1
        
        ] > tmp)mins[k-
        
          1
        
        ] =
        
           tmp;


        
        
          34
        
        
                      }


        
        
          35
        
        
                  }


        
        
          36
        
        
          for
        
        (
        
          int
        
         i = 
        
          0
        
         ; i < len; i++
        
          )


        
        
          37
        
        
                      delete [](f[i]);


        
        
          38
        
        
                  delete []f;


        
        
          39
        
        
          return
        
         mins[len-
        
          1
        
        
          ];


        
        
          40
        
        
              }


        
        
          41
        
        
          42
        
         };
      

 【版权声明】转载请注明出处: http://www.cnblogs.com/TenosDoIt/p/3421283.html

 
 

LeetCode:Palindrome Partitioning


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论