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.
Example:
Input: "aab"
Output: 1
Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut.
我们依旧沿袭palindrome partinioning的思路,可以推出这道题,但是时间复杂度比较高,为nnlen(word),第二个解法可以达到n*n
解法一:
public int minCut(String s) {
if (s.length() <= 1) return 0;
int[] dp = new int[s.length()];
for (int i = 1; i < s.length(); i++) {
int min = Integer.MAX_VALUE;
for (int p = 1; p <= i; p++) {
if (isPalindrome(s.substring(p, i+1))) {
min= Math.min(min, dp[p-1] + 1);
}
}
dp[i] = min;
if (isPalindrome(s.substring(0, i+1))) {
dp[i] = 0;
}
}
return dp[s.length() - 1];
}
private boolean isPalindrome(String s) {
if (s.length() <= 1) return true;
int l = 0;
int r = s.length() - 1;
while (l < r) {
if (s.charAt(l++) != s.charAt(r--)) {
return false;
}
}
return true;
}
解法二:由于abbba是palindrome,因此bbb也一定是,ab不是,那么cabc也一定不是,所以我们可以先用一个二维数组来存储从i到j是否是palindrome,然后ispal的时候直接看数组就能得到答案,这样可以减少对ispal函数的调用来优化时间。
public int minCut(String s) {
//todo: sanity checks
if (s == null || s.length() == 0) return 0;
//没有长度为0 的字符: off by one
boolean[][] dp = new boolean[s.length()][ s.length()];
//base case
dp[0][0] = true;
int[] mins = new int[s.length()];
mins[0] = 0;
for (int i = 1; i < s.length(); i++) {
int local = i ; //每个位置都切。 我们要求最小,所以给个大一点的值
for (int j = 0; j <= i; j++) {
char cj = s.charAt(j);
char ci = s.charAt(i);
if ( cj == ci &&(i - j < 2 || dp[j + 1] [i - 1])){
dp[j][i] = true;
local = j == 0 ? 0 : Math.min(local, mins[j-1] + 1);
}
}
mins[i] = local;
}
return mins[s.length() - 1];
}