Browse curriculum

Palindrome Partitioning II

Find the minimum number of cuts that split a string into palindromes, with a dynamic program over prefixes and a palindrome table filled along the way.

Problem Understanding

Palindrome Partitioning II: partition s so that every piece is a palindrome, using as few cuts as possible. Return that minimum number of cuts.

Examples: "aab" → 1 ("aa" | "b"); "a" → 0; "ab" → 1.

The Intuition: Decide the Last Piece

The best split of a prefix ends with some palindrome. Try them all:

  1. cuts[i] = fewest cuts for s[0..i].
  2. For each palindromic last piece s[j..i]: the prefix before it costs cuts[j − 1], plus one cut.
  3. If the whole prefix is a palindrome, it costs 0.

The palindrome checks reuse smaller answers like Palindromic Substrings, and the "best split of a prefix" structure is the one in Word Break.

Interactive Walkthrough

MARKED = LAST PIECE s[j..i] · TINTED = THE PREFIX BEFORE IT

cuts[i] ≤ i

s

a
b
a
c
d
c

cuts

·
·
·
·
·
·

i

:

cuts[i]

:

answer

:

 

cuts[i] = fewest cuts for s[0..i]. A string of length 6 never needs more than 5

Next

"a" is a palindrome from the start: s[0..0] needs 0 cuts

Free preview: the first 7 of 23 steps

s

The candidate last piece s[j..i] is marked (red when it is not a palindrome) and the prefix before it is tinted. The cuts row fills in left to right. Try All different for the worst case.

Dry Run Table

Input: "abacdc".

i Prefix Best last piece cuts[i]
0 a a 0
1 ab b 1
2 aba aba (whole) 0
3 abac c 1
4 abacd d 2
5 abacdc cdc 1

Answer: 1 ("aba" | "cdc").

The Solution Template

One double loop fills the palindrome table and the cuts together.

Palindrome Partitioning II Code
1var minCut = function(s) {
2 const n = s.length;
3 const pal = Array.from({ length: n }, () => new Array(n).fill(false));
4 const cuts = new Array(n);
5 for (let i = 0; i < n; i++) {
6 cuts[i] = i;
7 for (let j = 0; j <= i; j++) {
8 if (s[j] === s[i] && (i - j <= 1 || pal[j + 1][i - 1])) {
9 pal[j][i] = true;
10 if (j === 0) cuts[i] = 0;
11 else cuts[i] = Math.min(cuts[i], cuts[j - 1] + 1);
12 }
13 }
14 }
15 return cuts[n - 1];
16};

Edge Cases & Common Mistakes

  • Whole string is a palindrome: 0 cuts.
  • All characters different: n − 1 cuts.
  • Checking palindromes from scratch each time: O(n³); use the table.
  • Cuts vs pieces: pieces = cuts + 1; return cuts.
  • Backtracking all partitions: correct but exponential.

Summary

cuts[i] is the minimum over palindromic last pieces s[j..i] of cuts[j − 1] + 1 (0 if j = 0), with palindromes found from smaller ones as you go. O(n²) time and space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Start

    cuts[i] = i (cut between every character).

  2. Try last pieces

    For each i and each j ≤ i, if s[j..i] is a palindrome: cuts[i] = 0 when j = 0, else min(cuts[i], cuts[j - 1] + 1).

  3. Answer

    Return cuts[n - 1].

Frequently asked questions

How is this different from Palindrome Partitioning?

Palindrome Partitioning (LeetCode 131) lists every way to split the string, which takes exponential time and is solved with backtracking. Part II only asks for the fewest cuts, which a dynamic program over prefixes answers in O(n²).


Why is cuts[i] = cuts[j - 1] + 1?

Look at the last piece of the best split of s[0..i]: some palindrome s[j..i]. Everything before it, s[0..j-1], must itself be split optimally, which takes cuts[j - 1] cuts, and one more cut separates it from the last piece. Trying every palindromic last piece and taking the minimum gives cuts[i].


How is the palindrome table filled in time?

s[j..i] is a palindrome when s[j] == s[i] and the inside s[j+1..i-1] is a palindrome (or has length 0 or 1). That inside piece ends at i - 1, so its entry was filled while handling the previous i. One pass fills the table and the cuts together.


Can the space be reduced?

Yes. Instead of the n×n table, expand around every center (each character and each gap) and update cuts[right] = min(cuts[right], cuts[left - 1] + 1) for every palindrome found. Same O(n²) time, O(n) space.

New to the technique behind this problem? Watch it run step by step:

Dynamic Programming Visualization

Applying for software engineering roles? Free, no sign-up:

AI resume checker: match your resume to the job description