回文最少分割数
回文最少分割数
题目:回文最少分割
《程序员代码面试指南》第98题 P314 难度:尉★★☆☆
少有的做不出来的尉难度的题,但是这题在力扣上明明是hard!!!(不懂牛客&这本书怎么把这题定成简单(尉)的)。而且这题明明是动态规划题,却放在了字符串这一章,真的想不到用动态规划去做。就算知道用动态规划去解也做不出来┭┮﹏┭┮
言归正传,书上说,这题是一个经典的动态规划的题目。定义动态规划数组dp,dp[i]的含义是子串str[i..len-1]的回文最少分割数。那么dp[0]就是最后的结果。
从右往左依次计算dp[i]的值。假设 j 位置处在 i 与 len-1之间(i≤j<len),如果str[i..j]是回文串,那么dp[i]的值可能就是dp[j+1]+1。让 j 在 i 到 len-1位置上枚举,所有可能情况中的最小值就是dp[i]的值,即dp[i]=min{dp[j+1]+1(i≤j<len,且str[i..j]必须是回文串)}。
再定义一个二维数组boolean[][]p,如果p[i][j]为true,说明str[i..j]是回文串。如果p[i][j]为true,一定是以下三种情况:
- str[i..j]由1个字符组成
- str[i..j]由2个字符组成且2个字符相等
- str[i+1..j-1]是回文串(p[i+1][j-1]为true),且str[i]==str[j]
在计算dp数组的过程中,位置 i 是从右向左依次计算的。而对每一个 i 来说,又依次从 i 位置向右枚举所有的位置 j(i≤j<len)。所以对p[i][j]来说,p[i+1][j-1]的值一定计算过。
代码如下:
public int minCut(String str) {
if (str == null || str.equals("")) {
return 0;
}
char[] chas = str.toCharArray();
int len = chas.length;
int[] dp = new int[len + 1];
dp[len] = -1;
boolean[][] p = new boolean[len][len];
for (int i = len - 1; i >= 0; i--) {
dp[i] = Integer.MAX_VALUE;
for (int j = i; j < len; j++) {
if (chas[i] == chas[j] && (j - i < 2 || p[i + 1][j - 1])) {
p[i][j] = true;
dp[i] = Math.min(dp[i], dp[j + 1] + 1);
}
}
}
return dp[0];
}

浙公网安备 33010602011771号