您的位置:首页 > 编程语言 > Java开发

[Leetcode][JAVA] Palindrome Partitioning II

2014-10-27 10:02 411 查看
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()]即为结果

代码如下:

public int minCut(String s) {
int[] dp = new int[s.length()+1];
boolean[][] isP = new boolean[s.length()+1][s.length()+1];
for(int i=0;i<=s.length();i++)
{
isP[i][i]=true;
dp[i]=i-1;
}
for(int i=1;i<=s.length();i++)
for(int j=i-1;j>=0;j--)
if(i-j<2 || (isP[j+1][i-1] && s.charAt(i-1)==s.charAt(j))) {
isP[j][i]=true;
dp[i] = Math.min(dp[i], dp[j]+1);
}
return dp[s.length()];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: