Leetcode P0132"Palindrome Partitioning II" 题解

2020/09/12 Leetcode

博文中会简要介绍Leetcode P0132题目分析及解题思路。

“Palindrome Partitioning II”这道题是p0131的变形题,这道题可以用两次动态规划解决。一次是确定回文子串,另一次是一个一维费用背包问题。

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.

首先是确定所有回文子串。我们可以借鉴p0005的思路,得到如下递推表达式,

dp[i][j] = dp[i+1][j-1]+2, if dp[i+1][j-1] > 0 && s[i] == s[j]

其中dp[i+1][j-1] > 0表示字符串i+1到j-1的子串是一个回文串,s[i] == s[j]则意味着两端字符相等。

然后根据获得到的所有回文子串的区间,我们可以利用一维费用背包的思路,获得最小合法分割的次数。递推表达式如下,

dp2[0][i] = 0, if dp1[0][i] == true,
如果字符串s[0:i]是一个回文串,则切割次数为0,

dp2[0][i] = min(dp2[0][i], dp2[0][j-1]+1), if dp1[j][i] == true,
如果字符串s[j:i]是一个回文串,则切割次数为前j个字符,即s[0:j-1]的切割次数加上1,最终取得所有的最小值。

以下是Java的题解代码实现。

class Solution {
    public int minCut(String s) {
        int N = s.length();
        
        boolean[][] dp1 = new boolean[N][N];
        char[] chars = s.toCharArray();
        for (int idx=0; idx<N; ++idx) {
            dp1[idx][idx] = true;
            if (idx > 0 && chars[idx] == chars[idx-1])
                dp1[idx-1][idx] = true;
        }
        
        // DP1
        for (int i1=2; i1<N; ++i1) {
            for (int j2=i1-2; j2>=0; --j2) {
                dp1[j2][i1] = dp1[j2+1][i1-1] && (chars[i1] == chars[j2]);
            }
        }
        
        // DP2
        int[][] dp2 = new int[N][N];
        for (int i1=0; i1<N; ++i1) {
            dp2[0][i1] = Integer.MAX_VALUE;
            for (int j2=i1; j2>=0; --j2) {
                if (!dp1[j2][i1])
                    continue;
                
                dp2[0][i1] = Math.min(dp2[0][i1], (j2 == 0)? 0: dp2[0][j2-1]+1);
            }
        }
        
        return dp2[0][N-1];
    }
}

Search

    Table of Contents