Given a string s
. In one step you can insert any character at any index of the string.
Return the minimum number of steps to make s
a palindrome.
A Palindrome String is one that reads the same backward as well as forward.
For example:
Input: s = "zzazz" Output: 0 Explanation: The string "zzazz" is already a palindrome we do not need any insertions.
Input: s = "mbadm" Output: 2 Explanation: String can be "mbdadbm" or "mdbabdm".
Input: s = "leetcode" Output: 5 Explanation: Inserting 5 characters the string becomes "leetcodocteel".
Constraints:
1 <= s.length <= 500
s
consists of lowercase English letters.## Problem Description
The problem asks to find the minimum number of insertions needed to make a given string `s` a palindrome. A palindrome is a string that reads the same forwards and backward. We need to determine the fewest characters to insert into `s` at any position to achieve this property.
## Naive Approach (Brute Force)
A brute-force approach would involve trying all possible insertion combinations and checking if the resulting string is a palindrome. However, this is extremely inefficient due to the exponential number of possible insertions. For each position in the string, we could insert any character. The complexity of this approach is prohibitively high for even moderately sized strings.
## Optimal Solution: Dynamic Programming
A more efficient approach uses dynamic programming. The key idea is to find the longest palindromic subsequence (LPS) of the given string `s`. The number of insertions needed to make `s` a palindrome is equal to the difference between the length of `s` and the length of its LPS.
Let `dp[i][j]` be the length of the LPS of the substring `s[i...j]`. We can define the recurrence relation as follows:
1. If `s[i] == s[j]`, then `dp[i][j] = dp[i+1][j-1] + 2`
2. If `s[i] != s[j]`, then `dp[i][j] = max(dp[i+1][j], dp[i][j-1])`
The base case is when `i == j`, then `dp[i][j] = 1`.
Once we have the length of the LPS, say `lpsLength`, the minimum number of insertions is `s.length() - lpsLength`.
```java
class Solution {
public int minInsertions(String s) {
int n = s.length();
int[][] dp = new int[n][n];
for (int i = n - 1; i >= 0; i--) {
dp[i][i] = 1;
for (int j = i + 1; j < n; j++) {
if (s.charAt(i) == s.charAt(j)) {
dp[i][j] = dp[i + 1][j - 1] + 2;
} else {
dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return n - dp[0][n - 1];
}
}
class Solution:
def minInsertions(self, s: str) -> int:
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
dp[i][i] = 1
for j in range(i + 1, n):
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
return n - dp[0][n - 1]
The dynamic programming solution has a time complexity of O(n^2), where n is the length of the string. This is because we need to fill in the dp
table, which has dimensions n x n, requiring us to iterate through all possible substrings.
The space complexity is also O(n^2) because we store the dp
table, which has dimensions n x n.