Minimum Insertions to Make String Palindrome
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
0 ≤ s.length ≤ 12 - ◆
s consists of lowercase English letters
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Recursive Longest Palindromic Subsequence
BruteEvery character that isn't part of some palindromic subsequence of s is a character that will eventually need a mirrored twin inserted somewhere in the string. So the fewest insertions possible is exactly s.length() minus the length of s's longest palindromic subsequence — keep that subsequence untouched, and insert a matching partner for every leftover character. Finding that subsequence length recursively is simple: given a window [i, j], if the two ends match, both belong to the subsequence and the middle window [i+1, j-1] is solved the same way, contributing 2 more; if they don't match, drop whichever end doesn't help and keep the better of the two smaller windows. With no memoization, the same window gets re-solved from scratch every time a different sequence of drops lands on it, so the call count grows exponentially with the string length.
O(2ⁿ)O(n)1class Solution {
2 private String s;
3 public int minInsertions(String s) {
4 this.s = s;
5 int n = s.length();
6 if (n == 0) return 0;
7 return n - solve(0, n - 1);
8 }
9 private int solve(int i, int j) {
10 if (i > j) return 0;
11 if (i == j) return 1;
12 if (s.charAt(i) == s.charAt(j)) {
13 return 2 + solve(i + 1, j - 1);
14 }
15 return Math.max(solve(i + 1, j), solve(i, j - 1));
16 }
17}Optimal — Bottom-Up Interval DP
OptimalBuild the longest-palindromic-subsequence table bottom-up instead of re-deriving each window from scratch. dp[i][j] holds the longest palindromic subsequence length within s[i..j]. Every single character is a palindrome of length 1, so the diagonal starts there. Then grow outward by window length: if the two ends of a window match, dp[i][j] is 2 plus whatever the inner window already computed (or exactly 2 for a length-2 window); otherwise dp[i][j] takes the better of dropping the left end or the right end, both already sitting in the table from a shorter window. Once dp[0][n-1] is known, the answer falls straight out of the same formula as the brute force: n minus that length.
O(n²)O(n²)1class Solution {
2 public int minInsertions(String s) {
3 int n = s.length();
4 if (n == 0) return 0;
5 int[][] dp = new int[n][n];
6 for (int i = 0; i < n; i++) dp[i][i] = 1;
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)) {
11 dp[i][j] = (len == 2) ? 2 : dp[i + 1][j - 1] + 2;
12 } else {
13 dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
14 }
15 }
16 }
17 return n - dp[0][n - 1];
18 }
19}