Palindrome Partitioning II
Problem Statement
Imagine you’re a word sculptor with a string and a mission: slice it into the fewest possible pieces, each a perfect palindrome. This hard-level DP challenge is all about symmetry—how few cuts can you make to turn chaos into mirrored masterpieces? Given a string, return the minimum number of cuts needed.
Example
Input: s = "aab"
Output: 1 (Cut into "aa" | "b")
Input: s = "a"
Output: 0 (Already a palindrome)
Input: s = "abracadabra"
Output: 4 (e.g., "a" | "b" | "r" | "aca" | "dabra" needs at least 4 cuts)
Code
Java
Python
JavaScript
public class Solution {
public int minCut(String s) {
int n = s.length();
int[] dp = new int[n + 1];
boolean[][] isPal = new boolean[n][n];
for (int i = 0; i <= n; i++) dp[i] = i - 1; // Max cuts possible
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
if (s.charAt(j) == s.charAt(i) && (i - j <= 2 || isPal[j + 1][i - 1])) {
isPal[j][i] = true;
dp[i + 1] = Math.min(dp[i + 1], j == 0 ? 0 : dp[j] + 1);
}
}
}
return dp[n];
}
}
def min_cut(s):
n = len(s)
dp = list(range(n + 1)) # dp[i] = min cuts for s[0:i]
is_pal = [[False] * n for _ in range(n)]
for i in range(n):
min_cuts = i # Worst case: cut at every char
for j in range(i + 1):
if s[j] == s[i] and (i - j <= 2 or is_pal[j + 1][i - 1]):
is_pal[j][i] = True
min_cuts = min(min_cuts, 0 if j == 0 else dp[j] + 1)
dp[i + 1] = min_cuts
return dp[n]
function minCut(s) {
let n = s.length;
let dp = Array(n + 1).fill().map((_, i) => i - 1); // Max cuts
let isPal = Array(n).fill().map(() => Array(n).fill(false));
for (let i = 0; i < n; i++) {
let minCuts = i;
for (let j = 0; j <= i; j++) {
if (s[j] === s[i] && (i - j <= 2 || isPal[j + 1][i - 1])) {
isPal[j][i] = true;
minCuts = Math.min(minCuts, j === 0 ? 0 : dp[j] + 1);
}
}
dp[i + 1] = minCuts;
}
return dp[n];
}
Explanation
- DP Insight: dp[i] represents the minimum cuts needed for the substring s[0:i].
- Palindrome Check: Use a 2D table to mark palindromic substrings efficiently.
- Flow: For each position i, check all possible palindromic prefixes ending at i and minimize cuts based on prior results.
- Example Walkthrough: "aab" → dp[0]=-1, dp[1]=0 ("a"), dp[2]=0 ("aa"), dp[3]=1 ("aa"|"b").
- Optimization: Combines palindrome detection with DP to avoid redundant checks.
Note
Time complexity: O(n²), Space complexity: O(n²). Slice through the string with surgical precision—a DP masterpiece!
