首页 > 代码库 > [Leetcode][JAVA] Palindrome Partitioning II

[Leetcode][JAVA] 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.

很有难度的一道题,不看讨论几乎没法accept。

解法看来看去基本就是dp,与一般dp不一样的是,需要对两个特征进行dp记录。

1.使用dp[i]记录s.substring(0,i)的分割数,初始值为dp[i]=i-1. 0<=i<=s.length().

对于每个i, 可以找到至少一个j, 0<=j<=i-1, 使得s.substring(j,i)是回文字符串。找到所有这样的j的集合J。转移函数即为: dp[i] = min(dp[j]+1) (j∈J)

仅仅这么做还是会超时,那么还得继续优化。当前算法的重复处在于,每次判断s.substring(j,i)是否为回文字符串时,都需要遍历这个字符串,所以还需要第二个dp记录s.substring(j,i)是否为回文字符串。

2. 使用isP[i][j]记录s.substring(i,j)是否为回文字符串。0<=i<=s.length(),0<=j<=s.length(). 初始状态isP[i][i]=true (0<=i<=s.length()), isP[i][i+1]=true (0<=i<s.length()).

(PS,后面代码中没有初始化isP[i][i+1],因为在遍历过程中作特殊判断了(i-j<2时必定为真))

这样的话要判断s.substring(i,j)是否为回文字符串,只需要isP[i+1][j-1]为真且s.charAt(i-1)==s.charAt(j).

同时我们也可以明白,遍历的顺序应该是逐渐将i,j距离拉长的。

所以应该有两层循环,第一层循环是用来记录dp[i], i从1到s.length().

第二层循环记录isP[j][i](i已固定), j从i-1到0,反向遍历。

最后dp[s.length()]即为结果

代码如下:

 1     public int minCut(String s) { 2         int[] dp = new int[s.length()+1]; 3         boolean[][] isP = new boolean[s.length()+1][s.length()+1]; 4         for(int i=0;i<=s.length();i++) 5         { 6             isP[i][i]=true; 7             dp[i]=i-1; 8         } 9         for(int i=1;i<=s.length();i++)10             for(int j=i-1;j>=0;j--)11                 if(i-j<2 || (isP[j+1][i-1] && s.charAt(i-1)==s.charAt(j))) {12                     isP[j][i]=true;13                     dp[i] = Math.min(dp[i], dp[j]+1);14                 }15         return dp[s.length()];16     }

 

[Leetcode][JAVA] Palindrome Partitioning II