[leetcode] Palindrome Partitioning II 解题报告

题目链接: https://leetcode.com/problems/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.


思路:如果我们定义一个数组cut[n+1],cut[i]表示[i, n]区间有几个切点

我们要想将状态转化为子状态,那么可以从字符串右边往左扫描,逐渐增加子串长度,直到包含所有长度

那么以aabbefg为例:

0 1 2 3 4 5 6

a a b b e f g

      i   j         n

在[i, n]区间上,如果[i, j]上子串为回文数,则可以知道如果以这种切法,cut[i] = cut[j+1] + 1, 如果这种切法比原来的cut[i]得到的切点数要少,则更新cut[i],

因此可以得到状态转移方程为:

cut[i] = min(cut[i], cut[j+1] +1)

另外还有一个需要解决的问题就是判断回文数,可以同样使用二维dp来实现

dp[i][j]表示从i到j是否为回文数,将问题转化为子状态则为:

如果s[i] == s[j],即一个子串两端相等了,则判断去掉这两端字符的子串是否为回文数,这样就把回文问题分解成了子问题,其状态转移方程为

dp[i][j] = (s[i] == s[j] && (j-i < 2 || dp[i+1][j-1]))

其中j-i < 2 意思是如果i和j相邻或者相等并且s[i]==s[j]时,则可以直接判断是回文,不需要通过子状态转化

代码如下:

class Solution {
public:
    int minCut(string s) {
        int n = s.size();
        if(n == 0)
            return 0;
        int cut[n+1];
        bool palin[n][n];
        memset(palin,false, sizeof(palin));
        for(int i =0; i<= n; i++)
            cut[i] = n -i -1;
        for(int i =n-1; i >=0; i--)
        {
            for(int j = i; j< n; j++)
            {
                if(s[i] == s[j] && (j-i< 2 || palin[i+1][j-1]))
                {
                    palin[i][j] = true;
                    cut[i] = min(cut[i], cut[j+1]+1);
                }
            }
        }
        return cut[0];
    }
};

参考:http://fisherlei.blogspot.com/2013/03/leetcode-palindrome-partitioning-ii.html

http://www.acmerblog.com/leetcode-solution-palindrome-partitioning-ii-6228.html



你可能感兴趣的:(LeetCode,算法,动态规划)