Minimum Insertion Steps to Make a String Palindrome

LeetCode problem 1312. Minimum Insertion Steps to Make a String Palindrome.

## Problem description

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` palindrome.

A **Palindrome String** is one that reads the same backward as well as forward.

Example 1
**Input:** s = "zzazz"
**Output:** 0
**Explanation:** The string "zzazz" is already palindrome we don't need any insertions.
Example 2
**Input:** s = "mbadm"
**Output:** 2
**Explanation:** String can be "mbdadbm" or "mdbabdm".
Example 3
**Input:** s = "leetcode"
**Output:** 5
**Explanation:** Inserting 5 characters the string becomes "leetcodocteel".
Example 4
**Input:** s = "g"
**Output:** 0
Example 5
**Input:** s = "no"
**Output:** 1
Constraints
* `1 <= s.length <= 500`
* All characters of `s` are lower case English letters.

## Problem analysis

One important point to notice that this problem is built upon the Longest Palindromic Subsequence problem. Once we find out the longest palindromic subsequence, we will be able to insert the remaining characters in-between the palindromic subsequence to make the complete palindrome. So we can use dynamic programming to solve the problem.

See Longest Palindromic Subsequence#Problem analysis for the complete analysis.

The only difference is that the result equals the input string's length minus the length of the longest palindromic subsequence.

### Complexity analysis

Space complexity
Building the `dp` table takes O(n2) space. So the total space complexity is **O(n2)**.
Time complexity
Computing each cell requires a constant amount of computation. So the total time complexity is **O(n2)**.
## Solution

### C++ solution

```
class Solution {
public:
 int minInsertions(const std::string& s) {
 const int len = s.length();
 if (len <= 1) {
 return 0;
 }

 // dp[left][right]: maximum palindrome subsequence length
 // on input[left..right]
 int dp[len][len];
 memset(dp, 0, sizeof dp);
 for (int subLen = 1; subLen <= len; ++subLen) {
 for (int left = 0; left <= len - subLen; ++left) {
 int right = left + subLen - 1;

 if (subLen == 1) {
 dp[left][right] = 1;
 }
 else if (subLen == 2) {
 dp[left][right] = s[left] == s[right] ? 2 : 1;
 }
 else {
 // subLen >= 3
 if (s[left] == s[right]) {
 dp[left][right] = dp[left+1][right-1] + 2;
 }
 else {
 dp[left][right] = std::max(dp[left][right-1], dp[left+1][right]);
 }
 }
 }
 }

 return len - dp[0][len-1];
 }
};

```

### Java solution

```
class Solution {
 public int minInsertions(String s) {
 final int len = s.length();
 if (len <= 1) {
 return 0;
 }

 // dp[left][right]: maximum palindrome subsequence length
 // on input[left..right]
 int[][] dp = new int[len][len];
 for (int subLen = 1; subLen <= len; ++subLen) {
 for (int left = 0; left <= len - subLen; ++left) {
 int right = left + subLen - 1;

 if (subLen == 1) {
 dp[left][right] = 1;
 }
 else if (subLen == 2) {
 dp[left][right] = s.charAt(left) == s.charAt(right) ? 2 : 1;
 }
 else {
 // subLen >= 3
 if (s.charAt(left) == s.charAt(right)) {
 dp[left][right] = dp[left+1][right-1] + 2;
 }
 else {
 dp[left][right] = Integer.max(dp[left][right-1], dp[left+1][right]);
 }
 }
 }
 }

 return len - dp[0][len-1];
 }
}

```