Saturday, July 1, 2017

132. Palindrome Partitioning II

Version #2 DP - Expand from the center [TODO]

四刷 07/2022
Version #1 DP
写了一个bug就是当i为0的时候是从头切,相当于不用切一刀
Time O(N^2)
Space O(N^2)
Runtime: 85 ms, faster than 53.92% of Java online submissions for Palindrome Partitioning II.
Memory Usage: 48.3 MB, less than 45.73% of Java online submissions for Palindrome Partitioning II.
class Solution {
    public int minCut(String s) {
        int len = s.length();
        boolean[][] isPalin = new boolean[len][len];
        int[] dp = new int[len]; // min cut to make substring s[0, i] a valid palindrome partitioning
        for (int j = 0; j < len; j++) {
            // 0 1
            dp[j] = j; // cut into single characters
            for (int i = j; i >= 0; i--) {
                if (i == j) {
                    isPalin[i][j] = true;
                } else if (i + 1 == j) {
                    isPalin[i][j] = s.charAt(i) == s.charAt(j);
                } else {
                    isPalin[i][j] = s.charAt(i) == s.charAt(j) && isPalin[i + 1][j - 1];
                }
                //  ... [i, j] j + 1
                if (isPalin[i][j]) {
                    dp[j] = Math.min(dp[j], (i == 0 ? 0 : 1 + dp[i - 1]));
                }
            }
        }
        return dp[len - 1];
    }
}


三刷 06/2022

Version #1 DP - Expand 1 index

写了一个bug就是当start + 1 >= end - 1的状态是在dp里面搜不到的,需要特殊处理
Time O(N^2)
Space O(N^2)
Runtime: 45 ms, faster than 66.23% of Java online submissions for Palindrome Partitioning II.
Memory Usage: 48.2 MB, less than 50.29% of Java online submissions for Palindrome Partitioning II.

class Solution {
    public int minCut(String s) {
        int len = s.length();
        // dp[i] - min cuts to partition substring [0, i)
        int[] dp = new int[len + 1];
        boolean[][] palindromeMem = new boolean[len + 1][len + 1];
        for (int i = 1; i <= s.length(); i++) {
            dp[i] = Integer.MAX_VALUE;
            for (int j = i - 1; j >= 0; j--) {
                // If substring [j, i) is palindrome, then we can update min
                if (isPalindrome(s, j, i - 1, palindromeMem)) {
                    // System.out.printf("j=%d, i-1=%d, dp[j]=%d\n", j, i - 1, dp[j]);
                    dp[i] = Math.min(dp[i], dp[j] + (j == 0 ? 0 : 1));
                }
            }
            // System.out.printf("dp[%d]=%d\n", i, dp[i]);
        }
        return dp[s.length()];
    }
    private boolean isPalindrome(String s, int start, int end, boolean[][] palindromeMem) {
        if (start >= end) {
            palindromeMem[start][end] = true;
            return true;
        }
        // start . end
        palindromeMem[start][end] = s.charAt(start) == s.charAt(end) && (start + 1 >= end - 1 || palindromeMem[start + 1][end - 1]);
        return palindromeMem[start][end];
    }
}

2ND TRY
The solution below is better
49.96 %
class Solution {
    public int minCut(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int len = s.length();
// min[k] -> min cut we need to make [0, k] valid
int[] min = new int[len];
boolean[][] isPalindrome = new boolean[len][len];
for (int i = 0; i < len; i++) {
isPalindrome[i][i] = true;
}
//min[0] = 0;
// min[j] = Math.min(min[j - 1] + 1, Math.min(min[i - 1] + 1 && isPalindrome(i, j))
isPalindrome[0][0] = true;
for (int j = 1; j < len; j++) {
min[j] = min[j - 1] + 1; // i == j
for (int i = j - 1; i >= 0; i--) {
isPalindrome[i][j] = checkPalindrome(s, i, j, isPalindrome);
if (isPalindrome[i][j]) {
min[j] = Math.min(min[j], (i - 1 >= 0 ? min[i - 1] : -1) + 1);
}
}
}
return min[len - 1];
}

private boolean checkPalindrome(String s, int i, int j, boolean[][] isPalindrome) {
if (i >= j) {
return true;
}
// ij
// a b a
if (s.charAt(i) == s.charAt(j)) {
if (j == i + 1 || isPalindrome[i + 1][j - 1]) {
return true;
}
}
return false;
}
}

1ST TRY
 68.97 %
public class Solution {
    public int minCut(String s) {
        if (s == null || s.length() == 0) return 0;
        char[] array = s.toCharArray();
        int length = s.length();
        //minCut ends with index i
        int[] dp = new int[length];
        boolean[][] isPalindrome = new boolean[length][length];
        for (int right = 0; right < length; right++) {
            int min = right;
            for (int left = 0; left <= right; left++) {
                if (array[left] == array[right] && (left + 1 >= right - 1 || isPalindrome[left + 1][right - 1])) {
                    isPalindrome[left][right] = true;
                    min = left == 0 ? 0 : Math.min(min, dp[left - 1] + 1);
                }
            }
            dp[right] = min;
        }
        return dp[length - 1];
    }
}

No comments:

Post a Comment