zoukankan      html  css  js  c++  java
  • Leetcode#132 Palindrome Partitioning II

    原题地址

    动态规划题。

    最直观的想法就是用cut[i][j]表示子串s[i..j]的最小分割数,则有如下规则:

    1. 如果s[i..j]是回文串,则cut[i][j]=0

    2. 如果s[i..j]不是回文串,则枚举分割点,将原字符串切成两个子串,求解子问题。递推公式:cut[i][j] = min{cut[i][k] + cut[k+1][j] + 1},i <= k < j

    这样做的时间复杂度是O(n^3),可以引入额外的辅助条件对递推数组降维来优化。

    改进后是这样的:

    令cut[i]表示子串s[i..n-1]的最小分割数,则有如下规则:

    1. 如果s[i..n-1]是回文串,则cut[i] = 0

    2. 如果s[i..n-1]不是回文串,则枚举分割点,将原字符串切成两个子串,规定左边的那个串必须是回文串。递推公式:cut[i] = min{cut[k] + 1},i < k < n 且 s[i][k-1]是回文串

    时间复杂度降为O(n^2)

    上面并没有考虑判断回文串的计算量,实际上这部分包含着大量重复计算, 所以必须要把是否是回文串的信息记录下来,以后要判断的时候直接查表即可。

    算回文串也可以用动归解决。令palinp[i][j]表示s[i..j]是否是回文串,则palinp[i][j] = s[i] == s[j] && (j -i > 2 || palinp[i+1][j-1]),这部分的时间复杂度为O(n^2)

    代码:

     1 int minCut(string s) {
     2   if (s.empty())
     3     return 0;
     4 
     5   int len = s.length();
     6   bool **palinp = new bool*[len];
     7   int *cut = new int[len];
     8 
     9   for (int i = 0; i < len; i++)
    10     palinp[i] = new bool[len];
    11 
    12   for (int l = 1; l <= len; l++) {
    13     for (int i = 0; i + l <= len; i++) {
    14       palinp[i][i + l - 1] = (s[i] == s[i + l - 1]) && (l <= 2 || palinp[i + 1][i + l - 2]);
    15     }
    16   }
    17 
    18   for (int i = len - 1; i >= 0; i--) {
    19     if (palinp[i][len - 1])
    20       cut[i] = 0;
    21     else {
    22       cut[i] = len - i - 1;
    23       for (int j = i + 1; j < len; j++) {
    24         if (palinp[i][j - 1])
    25           cut[i] = min(cut[i], 1 + cut[j]);
    26       }
    27     }
    28   }
    29 
    30   return cut[0];
    31 }
  • 相关阅读:
    关于JDK中的设计模式
    关于Java中的构造方法和set方法()给属性赋值
    关于Object[]数组强转成Integer[]类型的数组.
    [ImportNew]Java中的Timer类和TimerTask类
    关于Linux最基本总结
    关于数组
    关于Linux系统和Windows系统中文件夹的命名规范
    关于数组集合之间的转换
    关于Java获取系统信息
    关于Windows常用命令
  • 原文地址:https://www.cnblogs.com/boring09/p/4236327.html
Copyright © 2011-2022 走看看