Palindrome Partitioning II
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ s.length ≤ 12 - ◆
s consists of lowercase English letters only
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Palindrome Table + Recursion Without Memoization
BruteKnowing which substrings are palindromes is cheap to work out once, up front, with a small interval table: a length-1 piece is always a palindrome, and a longer piece is one exactly when its outer two letters match and whatever's strictly between them is itself already known to be a palindrome. The expensive part is deciding *where* to cut. From a given starting position, try ending the next piece at every later index that keeps that piece a palindrome, and recurse on what's left — but without remembering an already-solved starting position, the same tail of the string gets re-solved from scratch every time a different earlier cut happens to land on it.
O(2ⁿ)O(n²)1class Solution {
2 private boolean[][] isPal;
3 public int minCut(String s) {
4 int n = s.length();
5 isPal = new boolean[n][n];
6 for (int i = 0; i < n; i++) isPal[i][i] = true;
7 for (int len = 2; len <= n; len++) {
8 for (int i = 0; i + len - 1 < n; i++) {
9 int j = i + len - 1;
10 if (s.charAt(i) == s.charAt(j) && (len == 2 || isPal[i + 1][j - 1])) isPal[i][j] = true;
11 }
12 }
13 return solve(s, 0);
14 }
15 private int solve(String s, int start) {
16 if (start == s.length()) return -1;
17 if (isPal[start][s.length() - 1]) return 0;
18 int best = Integer.MAX_VALUE;
19 for (int end = start; end < s.length(); end++) {
20 if (isPal[start][end]) {
21 int cuts = 1 + solve(s, end + 1);
22 if (cuts < best) best = cuts;
23 }
24 }
25 return best;
26 }
27}Optimal — Bottom-Up Cut-Count DP
OptimalBuild the same palindrome table first, then work forward instead of recursing backward: dp[i] holds the fewest cuts needed for the prefix ending at index i. If that whole prefix is already a palindrome, dp[i] is 0. Otherwise, try every earlier position j — if the piece from j+1 to i is a palindrome, then dp[i] can be dp[j] + 1 (settle the prefix up to j optimally, then take one more cut for this new palindromic piece). Because every dp[j] with j < i is already finished by the time i is reached, no position's answer is ever recomputed.
O(n²)O(n²)1class Solution {
2 public int minCut(String s) {
3 int n = s.length();
4 boolean[][] isPal = new boolean[n][n];
5 for (int i = 0; i < n; i++) isPal[i][i] = true;
6 for (int len = 2; len <= n; len++) {
7 for (int i = 0; i + len - 1 < n; i++) {
8 int j = i + len - 1;
9 if (s.charAt(i) == s.charAt(j) && (len == 2 || isPal[i + 1][j - 1])) isPal[i][j] = true;
10 }
11 }
12 int[] dp = new int[n];
13 for (int i = 0; i < n; i++) {
14 if (isPal[0][i]) { dp[i] = 0; continue; }
15 dp[i] = Integer.MAX_VALUE;
16 for (int j = 0; j < i; j++) {
17 if (isPal[j + 1][i] && dp[j] + 1 < dp[i]) dp[i] = dp[j] + 1;
18 }
19 }
20 return dp[n - 1];
21 }
22}