Problem 2 Palindrome Partitioning II可以当母体练
区间型DP + NK问题
NK问题: divide s into k nonempty disjoint substrings
dp[k][n] represents the minimum number of characters you need to change to divide the length n string into k parts
dp[1][n] = 这一段需要change多少个就是多少
dp[k][i] = min (dp[k- 1][j] + 右小段需要change多少个就是多少个)
逻辑: 先知道给你一段,最少需要change几个把它变成回文
numberOfChange[i][j] represents from i to j, the minimum number of characters you need to change to make i to j a palindrome
numberOfChange[i][i] = 0
numberOfChange[i][i+1] = s[i] != s[j]? 1: 0
numberOfChange[i][j] =
s[i] = s[j]: numberOfChange[i][j] = numberOfChange[i+ 1][j - 1]
s[i] != s[j]: 1 + numberOfChange[i + 1][j - 1]
```java
/*
clarification:
assumption:
high level:
middle level:
TC &SC:
Cost: 30mins +30 mins + 30mins + 30mins
Comment:
- 见dp讲章多种解法,一般dp,pure recursion,之前自己写的backTrakcing, 区间dp
- 一个是在每个位置上,切或者不切的dp,空间小,但是时间长
- 另一个是一刀一刀切,空间大,但是时间少了?不是 是把isPalindrome写成dp
- dp[i] length i, how many cutting we need for it?
- dp[i] = min (dp[j] + 1) for all j such that j < i if isPal(j + 1, i)
= 0, iff isPal(0, i-1)
- dp[i][j]: represent [i, j] (including i and j)if they are palindrome,
base case
induction rule:
dp[i][j] =
if s.charAt(i) = s.charAt(j) dp[i][j] = dp[i+1][j- 1]
if s.charAt(i) != s.charAt(j) dp[i][j] = false;
filling:
from buttom to up and from right to left
return value
dp[i][j]
*/
class Solution {
public int minCut(String s) {
// sanity check
// intitial
int[] dp = new int[s.length() + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
buildValidPali(s);
dp[0] = 0;
// System.out.println(Arrays.deepToString(isPali));
// dp
for (int i = 1; i <= s.length(); i++) {
if (isPalindrome(s, 0, i-1)) { //!!!注意区别!!!!!!!
// if (isPalindrome2(s, i-1, 0)) {
// System.out.println(isPalindrome(s, 0 , i-1));
// System.out.println(isPalindrome2(s, i-1, 0));
dp[i] = 0;
} else {
for (int j = 0; j < i; j++) {
// if (dp[j] != Integer.MAX_VALUE && isPalindrome(s, j, i -1)) {
if (dp[j] != Integer.MAX_VALUE && isPalindrome2(s, i-1, j)) { ///
// System.out.println(isPalindrome(s, j , i-1));
// System.out.println(isPalindrome2(s, i-1, j));
dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
}
}
// return value
return dp[s.length()];
}
private boolean isPalindrome(String s, int i, int j) { // 注意有没有off by 1
while (i < j) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
i++;
j--;
}
return true;
}
private boolean[][] isPali;
private void buildValidPali(String s) {
isPali = new boolean[s.length()][s.length()];
for (int i = s.length() - 1; i >= 0; i --) {
for (int j = i; j < s.length(); j++) { //这个不是一个完整的matrix,因为没有j< i的情况
if (i == j) {
isPali[i][j] = true;
} else if (j == i + 1) {
isPali[i][j] = s.charAt(i) == s.charAt(j)? true: false;
} else {
if (s.charAt(i)== s.charAt(j)) {
isPali[i][j] = isPali[i+ 1][j- 1];
}
}
}
}
}
private boolean isPalindrome2(String s, int i, int j) {
return isPali[j][i];
}
}
```// Some code
Last updated