πΉ Key Idea (MOST IMPORTANT)
π Use Longest Palindromic Subsequence (LPS)
Minimum Insertions = n - LPS
πΉ Why this works?
- LPS = longest part already palindrome
- Remaining characters must be inserted to fix symmetry
π So:
Total characters β already palindrome part = insertions needed
πΉ Convert to LCS
LPS(s) = LCS(s, reverse(s))
π₯ Final Formula
Min Insertions = n - LCS(s, reverse(s))
πΉ Example
s = "abcaa"
Reverse:
"aacba"
π LCS = "aca" β length = 3
Min Insertions = 5 - 3 = 2
πΉ Code (C++)
int lcs(string s1, string s2) {
int n = s1.size(), m = s2.size();
vector<vector<int>> dp(n+1, vector<int>(m+1, 0));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s1[i-1] == s2[j-1])
dp[i][j] = 1 + dp[i-1][j-1];
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[n][m];
}
int minInsertions(string s) {
string t = s;
reverse(t.begin(), t.end());
int lps = lcs(s, t);
return s.size() - lps;
}
πΉ Space Optimized π
int lcs(string s1, string s2) {
int n = s1.size(), m = s2.size();
vector<int> prev(m+1, 0), curr(m+1, 0);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(s1[i-1] == s2[j-1])
curr[j] = 1 + prev[j-1];
else
curr[j] = max(prev[j], curr[j-1]);
}
prev = curr;
}
return prev[m];
}
πΉ Alternative DP (Direct without LCS)
π Define:
dp[i][j] = min insertions to make s[i..j] palindrome
Transition:
- If match:
dp[i][j] = dp[i+1][j-1]
- If not:
dp[i][j] = 1 + min(dp[i+1][j], dp[i][j-1])
πΉ Code (Direct DP)
int minInsertions(string s) {
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n, 0));
for(int len = 2; len <= n; len++){
for(int i = 0; i + len - 1 < n; i++){
int j = i + len - 1;
if(s[i] == s[j])
dp[i][j] = dp[i+1][j-1];
else
dp[i][j] = 1 + min(dp[i+1][j], dp[i][j-1]);
}
}
return dp[0][n-1];
}
πΉ Complexity
| Approach | Time | Space |
|---|---|---|
| LCS-based | O(nΒ²) | O(nΒ²) / O(n) |
| Direct DP | O(nΒ²) | O(nΒ²) |
π§ Key Pattern
π Whenever you see:
- βMake palindromeβ
- βMinimum insert/deleteβ
β‘οΈ Think:
Use LPS (LCS with reverse)
π₯ Interview Tip
If asked:
βMinimum insertions to make palindrome?β
π Answer:
βWe compute LPS using LCS with reverse string, then subtract from length.β
β‘ Summary
- Convert β LPS
- LPS β LCS(s, reverse(s))
- Answer β
n - LPS
π Best Optimized Approach
(From Dynamic Programming)
πΉ Final Optimized Idea
We use:
Min Insertions = n - LCS(s, reverse(s))
π Optimize LCS to O(n) space
π₯ Fully Optimized Code (O(nΒ²) time, O(n) space)
int minInsertions(string s) {
int n = s.size();
string t = s;
reverse(t.begin(), t.end());
vector<int> prev(n+1, 0), curr(n+1, 0);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(s[i-1] == t[j-1])
curr[j] = 1 + prev[j-1];
else
curr[j] = max(prev[j], curr[j-1]);
}
prev = curr;
}
int lps = prev[n];
return n - lps;
}
πΉ Space Complexity
| Approach | Space |
|---|---|
| Normal DP | O(nΒ²) |
| Optimized (above) | β O(n) |
π₯ Can we optimize more?
π β NO (for general case)
Why?
- You must compare all pairs β needs O(nΒ²) time
- LCS inherently requires quadratic time
πΉ Alternative (Direct DP optimized?)
π Direct DP:
dp[i][j] = min insertions
β Cannot reduce to O(n) easily
π Because it depends on:
dp[i+1][j]dp[i][j-1]dp[i+1][j-1]
π§ Final Takeaway
π Best you can do:
| Metric | Optimal |
|---|---|
| Time | O(nΒ²) |
| Space | β O(n) |
β‘ Interview Answer (Perfect π₯)
If asked:
βCan you optimize space?β
π Say:
βYes, by computing LCS with a 1D DP array, reducing space to O(n) while keeping time O(nΒ²). Further optimization isnβt possible due to dependency structure.β
π Extra Insight (Advanced)
π If asked harder:
- You can use Hirschbergβs Algorithm
- Space β O(n)
- Still O(nΒ²) time
- Can reconstruct palindrome too
If you want next π
I can show:
β
Build the actual palindrome string (very important)
β
Minimum deletions version
β
Hard interview problems
Just tell me π
Top comments (0)