1. Top-Down Recursion with Memoization
Intuition
Define minCuts(i) as the minimum cuts needed for suffix s[i...n-1]. If s[i...n-1] is a palindrome, return 0. Otherwise, for every j from i to n - 1, if s[i...j] is a palindrome, candidate cuts are 1 + minCuts(j + 1). Return the minimum across all valid j.
When to apply: Basic recursive formulation.
Algorithm
- Initialize
memoarray of sizenwith -1. - Helper
solve(i): - If
isPalindrome(s[i...n-1]): return 0. - If
memo[i] != -1: returnmemo[i]. -
minCuts = Infinity. - For
jfromiton - 1: - If
isPalindrome(s[i...j]): -
minCuts = min(minCuts, 1 + solve(j + 1)). -
memo[i] = minCuts. - Return
minCuts.
Interactive Trace
2 of 2 questions left todayInitialize dp = [0, 1, 2]
Initialize dp = [0, 1, 2].
#include <iostream>#include <string>#include <vector>#include <algorithm> class Solution { bool isPalindrome(const std::string& s, int i, int j) { while (i < j) { if (s[i++] != s[j--]) return false; } return true; } int solve(int i, const std::string& s, std::vector<int>& memo) { int n = s.size(); if (i >= n || isPalindrome(s, i, n - 1)) return 0; if (memo[i] != -1) return memo[i]; int ans = n; for (int j = i; j < n; ++j) { if (isPalindrome(s, i, j)) { ans = std::min(ans, 1 + solve(j + 1, s, memo)); } } return memo[i] = ans; }public: int minCut(std::string s) { int n = s.size(); std::vector<int> memo(n, -1); return solve(0, s, memo); }}; int main() { Solution sol; std::cout << sol.minCut("aab") << std::endl; // 1 std::cout << sol.minCut("a") << std::endl; // 0 return 0;}Time & Space Complexity
- Time complexity:
O(N^3)— N states, each loop runs O(N) with O(N) palindrome check per iteration. - Space complexity:
O(N)
Why Brute Force Doesn't Scale:
Combining center expansion with 1D DP achieves O(N2) time and O(N) space.
Only stores a single 1D array of integers.