Open In App

Minimum insertions to form a palindrome

Last Updated : 09 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string s, the task is to find the minimum number of characters to be inserted to convert it to a palindrome.

Examples:

Input: s = "geeks"
Output: 3
Explanation: "skgeegks" is a palindromic string, which requires 3 insertions.

Input: s= "abcd"
Output: 3
Explanation: "abcdcba" is a palindromic string.

Input: s= "aba"
Output: 0
Explanation: Given string is already a palindrome hence no insertions are required.

Using Recursion - O(2^n) Time and O(n) Space

The minimum number of insertions in the string str[l…..h] can be given as:  

  • if str[l] is equal to str[h] findMinInsertions(str[l+1…..h-1])
  • otherwise, min(findMinInsertions(str[l…..h-1]), findMinInsertions(str[l+1…..h])) + 1
C++
// C++ approach to find Minimum 
// insertions to form a palindrome
#include<bits/stdc++.h>
using namespace std;

// Recursive function to find  
// minimum number of insertions
int minRecur(string &s, int l, int h) {
  
  	// Base case
    if (l >= h) return 0;
  
  	// if first and last char are same 
  	// then no need to insert element
  	if(s[l] == s[h]) {
      	return minRecur(s, l + 1, h - 1);
    }
  
  	// Insert at begining or insert at end
  	return min(minRecur(s, l + 1, h), 
               minRecur(s, l, h - 1)) + 1;
}

int findMinInsertions(string &s) {
 	return minRecur(s, 0, s.size() - 1);
}

int main() {
    string s = "geeks";
    cout << findMinInsertions(s);
    return 0;
}
Java
// Java approach to find Minimum 
// insertions to form a palindrome
class GfG {

    // Recursive function to find  
    // minimum number of insertions
    static int minRecur(String s, int l, int h) {
      
        // Base case
        if (l >= h) return 0;
      
        // if first and last char are same 
        // then no need to insert element
        if (s.charAt(l) == s.charAt(h)) {
            return minRecur(s, l + 1, h - 1);
        }
      
        // Insert at begining or insert at end
        return Math.min(minRecur(s, l + 1, h), 
                        minRecur(s, l, h - 1)) + 1;
    }

    static int findMinInsertions(String s) {
        return minRecur(s, 0, s.length() - 1);
    }

    public static void main(String[] args) {
        String s = "geeks";
        System.out.println(findMinInsertions(s));
    }
}
Python
# Python approach to find Minimum 
# insertions to form a palindrome

# Recursive function to find  
# minimum number of insertions
def minRecur(s, l, h):
  
    # Base case
    if l >= h:
        return 0
  
    # if first and last char are same 
    # then no need to insert element
    if s[l] == s[h]:
        return minRecur(s, l + 1, h - 1)
  
    # Insert at begining or insert at end
    return min(minRecur(s, l + 1, h), 
               minRecur(s, l, h - 1)) + 1

def findMinInsertions(s):
    return minRecur(s, 0, len(s) - 1)

if __name__ == "__main__":
    s = "geeks"
    print(findMinInsertions(s))
C#
// C# approach to find Minimum 
// insertions to form a palindrome
using System;

class GfG {

    // Recursive function to find  
    // minimum number of insertions
    static int minRecur(string s, int l, int h) {
      
        // Base case
        if (l >= h) return 0;
      
        // if first and last char are same 
        // then no need to insert element
        if (s[l] == s[h]) {
            return minRecur(s, l + 1, h - 1);
        }
      
        // Insert at begining or insert at end
        return Math.Min(minRecur(s, l + 1, h), 
                        minRecur(s, l, h - 1)) + 1;
    }

    static int findMinInsertions(string s) {
        return minRecur(s, 0, s.Length - 1);
    }

    static void Main(string[] args) {
        string s = "geeks";
        Console.WriteLine(findMinInsertions(s));
    }
}
JavaScript
// JavaScript approach to find Minimum 
// insertions to form a palindrome

// Recursive function to find  
// minimum number of insertions
function minRecur(s, l, h) {
  
    // Base case
    if (l >= h) return 0;
  
    // if first and last char are same 
    // then no need to insert element
    if (s[l] === s[h]) {
        return minRecur(s, l + 1, h - 1);
    }
  
    // Insert at begining or insert at end
    return Math.min(minRecur(s, l + 1, h), 
                    minRecur(s, l, h - 1)) + 1;
}

function findMinInsertions(s) {
    return minRecur(s, 0, s.length - 1);
}

const s = "geeks";
console.log(findMinInsertions(s));

Output
3

Using Top-Down DP (Memoization) - O(n^2) Time and O(n^2) Space

If we notice carefully, we can observe that the above recursive solution holds the following two properties of Dynamic Programming:

1. Optimal Substructure: The minimum number of insertions required to make the substring str[l...h] a palindrome depends on the optimal solutions of its subproblems. If str[l] is equal to str[h] then we call recursive call on l + 1 and h - 1 other we make two recursive call to get optimal answer.

2. Overlapping Subproblems: When using a recursive approach, we notice that certain subproblems are computed multiple times. To avoid this redundancy, we can use memoization by storing the results of already computed subproblems in a 2D array.

The problem involves changing two parameters: l (starting index) and h (ending index). Hence, we need to create a 2D array of size (n x n) to store the results, where n is the length of the string. By using this 2D array, we can efficiently reuse previously computed results and optimize the solution.

C++
// C++ approach to find Minimum 
// insertions to form a palindrome
#include<bits/stdc++.h>
using namespace std;

// Recursive function to find  
// minimum number of insertions
int minRecur(string &s, int l, int h, vector<vector<int>> &memo) {
  
  	// Base case
    if (l >= h) return 0;
    
    // If value is memoized 
    if (memo[l][h] != -1) return memo[l][h];
  
  	// if first and last char are same 
  	// then no need to insert element
  	if(s[l] == s[h]) {
      	return memo[l][h] = minRecur(s, l + 1, h - 1, memo);
    }
  
  	// Insert at begining or insert at end
  	return memo[l][h] = min(minRecur(s, l + 1, h, memo), 
               minRecur(s, l, h - 1, memo)) + 1;
}

int findMinInsertions(string &s) {
    int n = s.length();
    vector<vector<int>> memo(n, vector<int>(n, -1));
    
 	return minRecur(s, 0, n - 1, memo);
}

int main() {
    string s = "geeks";
    cout << findMinInsertions(s);
    return 0;
}
Java
// Java approach to find Minimum 
// insertions to form a palindrome
class GfG {

    // Recursive function to find  
    // minimum number of insertions
    static int minRecur(String s, int l, int h, int[][] memo) {
      
        // Base case
        if (l >= h) return 0;
        
        // If value is memoized 
        if (memo[l][h] != -1) return memo[l][h];
      
        // if first and last char are same 
        // then no need to insert element
        if (s.charAt(l) == s.charAt(h)) {
            return memo[l][h] = minRecur(s, l + 1, h - 1, memo);
        }
      
        // Insert at begining or insert at end
        return memo[l][h] = Math.min(minRecur(s, l + 1, h, memo), 
                                     minRecur(s, l, h - 1, memo)) + 1;
    }

    static int findMinInsertions(String s) {
        int n = s.length();
        int[][] memo = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                memo[i][j] = -1;
            }
        }
        return minRecur(s, 0, n - 1, memo);
    }

    public static void main(String[] args) {
        String s = "geeks";
        System.out.println(findMinInsertions(s));
    }
}
Python
# Python approach to find Minimum 
# insertions to form a palindrome

# Recursive function to find  
# minimum number of insertions
def minRecur(s, l, h, memo):
  
    # Base case
    if l >= h:
        return 0

    # If value is memoized 
    if memo[l][h] != -1:
        return memo[l][h]
  
    # if first and last char are same 
    # then no need to insert element
    if s[l] == s[h]:
        memo[l][h] = minRecur(s, l + 1, h - 1, memo)
        return memo[l][h]
  
    # Insert at begining or insert at end
    memo[l][h] = min(minRecur(s, l + 1, h, memo), 
                     minRecur(s, l, h - 1, memo)) + 1
    return memo[l][h]

def findMinInsertions(s):
    n = len(s)
    memo = [[-1] * n for _ in range(n)]
    return minRecur(s, 0, n - 1, memo)

if __name__ == "__main__":
    s = "geeks"
    print(findMinInsertions(s))
C#
// C# approach to find Minimum 
// insertions to form a palindrome
using System;

class GfG {

    // Recursive function to find  
    // minimum number of insertions
    static int minRecur(string s, int l, int h, int[,] memo) {
      
        // Base case
        if (l >= h) return 0;

        // If value is memoized 
        if (memo[l, h] != -1) return memo[l, h];
      
        // if first and last char are same 
        // then no need to insert element
        if (s[l] == s[h]) {
            return memo[l, h] = minRecur(s, l + 1, h - 1, memo);
        }
      
        // Insert at begining or insert at end
        return memo[l, h] = Math.Min(minRecur(s, l + 1, h, memo), 
                                     minRecur(s, l, h - 1, memo)) + 1;
    }

    static int findMinInsertions(string s) {
        int n = s.Length;
        int[,] memo = new int[n, n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                memo[i, j] = -1;
            }
        }
        return minRecur(s, 0, n - 1, memo);
    }

    static void Main(string[] args) {
        string s = "geeks";
        Console.WriteLine(findMinInsertions(s));
    }
}
JavaScript
// JavaScript approach to find Minimum 
// insertions to form a palindrome

// Recursive function to find  
// minimum number of insertions
function minRecur(s, l, h, memo) {
  
    // Base case
    if (l >= h) return 0;
    
    // If value is memoized 
    if (memo[l][h] !== -1) return memo[l][h];
  
    // if first and last char are same 
    // then no need to insert element
    if (s[l] === s[h]) {
        return memo[l][h] = minRecur(s, l + 1, h - 1, memo);
    }
  
    // Insert at begining or insert at end
    return memo[l][h] = Math.min(minRecur(s, l + 1, h, memo), 
                                 minRecur(s, l, h - 1, memo)) + 1;
}

function findMinInsertions(s) {
    const n = s.length;
    const memo = Array.from({ length: n }, () => Array(n).fill(-1));
    return minRecur(s, 0, n - 1, memo);
}

const s = "geeks";
console.log(findMinInsertions(s));

Output
3

Using Bottom-Up DP (Tabulation) - O(n^2) Time and O(n^2) Space

The iterative approach for finding the minimum number of insertions needed to make a string palindrome follows a similar concept to the recursive solution but builds the solution in a bottom-up manner using a 2D dynamic programming table.

Base Case:

  • if l == h than dp[l][h] = 0. Where 0 <= l <= n - 1
  • If the substring has two characters (h == l + 1), we check if they are the same. If they are, dp[l][h] = 0, otherwise, dp[l][h] = 1.

Recursive Case:

  • If str[l] == str[h], then dp[l][h] = dp[l+1][h-1].
  • Otherwise, dp[l][h] = min(dp[l+1][h], dp[l][h-1]) + 1. 
C++
// C++ approach to find Minimum 
// insertions to form a palindrome
#include<bits/stdc++.h>
using namespace std;

// Function to find minimum insertions 
// to make string palindrome
int findMinInsertions(string &s) {
    int n = s.size();
    
    // dp[i][j] will store the minimum number of insertions needed
    // to convert str[i..j] into a palindrome
    vector<vector<int>> dp(n, vector<int>(n, 0));

    // len is the length of the substring
    for (int len = 2; len <= n; len++) {
        for (int l = 0; l <= n - len; l++) {
          
          	// ending index of the current substring
            int h = l + len - 1; 

            // If the characters at both ends are 
          	// equal, no new insertions needed
            if (s[l] == s[h]) {
                dp[l][h] = dp[l + 1][h - 1];
            } else {
                
                // Insert at the beginning or at the end
                dp[l][h] = min(dp[l + 1][h], dp[l][h - 1]) + 1;
            }
        }
    }

    // The result is in dp[0][n-1] which 
  	// represents the entire string
    return dp[0][n - 1];
}

int main() {
    string s = "geeks";
    cout << findMinInsertions(s);
    return 0;
}
Java
// Java approach to find Minimum 
// insertions to form a palindrome
class GfG {

    // Function to find minimum insertions 
    // to make string palindrome
    static int findMinInsertions(String s) {
        int n = s.length();
        
        // dp[i][j] will store the minimum number of insertions needed
        // to convert str[i..j] into a palindrome
        int[][] dp = new int[n][n];

        // len is the length of the substring
        for (int len = 2; len <= n; len++) {
            for (int l = 0; l <= n - len; l++) {
              
                // ending index of the current substring
                int h = l + len - 1; 

                // If the characters at both ends are 
                // equal, no new insertions needed
                if (s.charAt(l) == s.charAt(h)) {
                    dp[l][h] = dp[l + 1][h - 1];
                } else {
                    
                    // Insert at the beginning or at the end
                    dp[l][h] = Math.min(dp[l + 1][h], dp[l][h - 1]) + 1;
                }
            }
        }

        // The result is in dp[0][n-1] which 
        // represents the entire string
        return dp[0][n - 1];
    }

    public static void main(String[] args) {
        String s = "geeks";
        System.out.println(findMinInsertions(s));
    }
}
Python
# Python approach to find Minimum 
# insertions to form a palindrome

# Function to find minimum insertions 
# to make string palindrome
def findMinInsertions(s):
    n = len(s)
    
    # dp[i][j] will store the minimum number of insertions needed
    # to convert str[i..j] into a palindrome
    dp = [[0] * n for _ in range(n)]

    # len is the length of the substring
    for length in range(2, n + 1):
        for l in range(n - length + 1):
            
            # ending index of the current substring
            h = l + length - 1

            # If the characters at both ends are 
            # equal, no new insertions needed
            if s[l] == s[h]:
                dp[l][h] = dp[l + 1][h - 1]
            else:
                
                # Insert at the beginning or at the end
                dp[l][h] = min(dp[l + 1][h], dp[l][h - 1]) + 1

    # The result is in dp[0][n-1] which 
    # represents the entire string
    return dp[0][n - 1]

if __name__ == "__main__":
    s = "geeks"
    print(findMinInsertions(s))
C#
// C# approach to find Minimum 
// insertions to form a palindrome
using System;

class MainClass {

    // Function to find minimum insertions 
    // to make string palindrome
    static int findMinInsertions(string s) {
        int n = s.Length;
        
        // dp[i,j] will store the minimum number of insertions needed
        // to convert str[i..j] into a palindrome
        int[,] dp = new int[n, n];

        // len is the length of the substring
        for (int len = 2; len <= n; len++) {
            for (int l = 0; l <= n - len; l++) {
              
                // ending index of the current substring
                int h = l + len - 1; 

                // If the characters at both ends are 
                // equal, no new insertions needed
                if (s[l] == s[h]) {
                    dp[l, h] = dp[l + 1, h - 1];
                } else {
                    
                    // Insert at the beginning or at the end
                    dp[l, h] = Math.Min(dp[l + 1, h], dp[l, h - 1]) + 1;
                }
            }
        }

        // The result is in dp[0,n-1] which 
        // represents the entire string
        return dp[0, n - 1];
    }

    static void Main(string[] args) {
        string s = "geeks";
        Console.WriteLine(findMinInsertions(s));
    }
}
JavaScript
// JavaScript approach to find Minimum 
// insertions to form a palindrome

// Function to find minimum insertions 
// to make string palindrome
function findMinInsertions(s) {
    const n = s.length;
    
    // dp[i][j] will store the minimum number of insertions needed
    // to convert str[i..j] into a palindrome
    const dp = Array.from({ length: n }, () => Array(n).fill(0));

    // len is the length of the substring
    for (let len = 2; len <= n; len++) {
        for (let l = 0; l <= n - len; l++) {
          
            // ending index of the current substring
            const h = l + len - 1;

            // If the characters at both ends are 
            // equal, no new insertions needed
            if (s[l] === s[h]) {
                dp[l][h] = dp[l + 1][h - 1];
            } else {
                
                // Insert at the beginning or at the end
                dp[l][h] = Math.min(dp[l + 1][h], dp[l][h - 1]) + 1;
            }
        }
    }

    // The result is in dp[0][n-1] which 
    // represents the entire string
    return dp[0][n - 1];
}

const s = "geeks";
console.log(findMinInsertions(s));

Output
3

Using Space Optimized DP – O(n ^ 2) Time and O(n) Space

The idea is to reuse the array in such a way that we store the results for the previous row in the same array while iterating through the columns.

C++
// C++ approach to find Minimum 
// insertions to form a palindrome
#include<bits/stdc++.h>
using namespace std;

// Function to find minimum insertions 
// to make string palindrome
int findMinInsertions(string &s) {
    int n = s.size();
    vector<int> dp(n, 0);
    
    // Iterate over each character from right to left
    for (int l = n - 2; l >= 0; l--) {
      
      	// This represents dp[l+1][h-1] from the previous row
        int prev = 0; 
        for (int h = l + 1; h < n; h++) {
          
          	// Save current dp[h] before overwriting
            int temp = dp[h]; 
            
            if (s[l] == s[h]) {
              
              	// No new insertion needed if characters match
                dp[h] = prev; 
            } else {
              
              	// Take min of two cases + 1
                dp[h] = min(dp[h], dp[h - 1]) + 1; 
            }
            
          	// Update prev for the next column
            prev = temp; 
        }
    }
    
    return dp[n - 1];
}

int main() {
    string s = "geeks";
    cout << findMinInsertions(s);
    return 0;
}
Java
// Java approach to find Minimum 
// insertions to form a palindrome
class GfG {

    // Function to find minimum insertions 
    // to make string palindrome
    static int findMinInsertions(String s) {
        int n = s.length();
        int[] dp = new int[n];
        
        // Iterate over each character from right to left
        for (int l = n - 2; l >= 0; l--) {
            
            // This represents dp[l+1][h-1] from the previous row
            int prev = 0; 
            for (int h = l + 1; h < n; h++) {
                
                // Save current dp[h] before overwriting
                int temp = dp[h]; 
                
                if (s.charAt(l) == s.charAt(h)) {
                    
                    // No new insertion needed if characters match
                    dp[h] = prev; 
                } else {
                    
                    // Take min of two cases + 1
                    dp[h] = Math.min(dp[h], dp[h - 1]) + 1; 
                }
                
                // Update prev for the next column
                prev = temp; 
            }
        }
        
        return dp[n - 1];
    }

    public static void main(String[] args) {
        String s = "geeks";
        System.out.println(findMinInsertions(s));
    }
}
Python
# Python approach to find Minimum 
# insertions to form a palindrome

# Function to find minimum insertions 
# to make string palindrome
def findMinInsertions(s):
    n = len(s)
    dp = [0] * n

    # Iterate over each character from right to left
    for l in range(n - 2, -1, -1):
        
        # This represents dp[l+1][h-1] from the previous row
        prev = 0 
        for h in range(l + 1, n):
            
            # Save current dp[h] before overwriting
            temp = dp[h] 
            
            if s[l] == s[h]:
                
                # No new insertion needed if characters match
                dp[h] = prev 
            else:
                
                # Take min of two cases + 1
                dp[h] = min(dp[h], dp[h - 1]) + 1 
            
            # Update prev for the next column
            prev = temp 

    return dp[n - 1]

if __name__ == "__main__":
    s = "geeks"
    print(findMinInsertions(s))
C#
// C# approach to find Minimum 
// insertions to form a palindrome
using System;

class GfG {

    // Function to find minimum insertions 
    // to make string palindrome
    static int findMinInsertions(string s) {
        int n = s.Length;
        int[] dp = new int[n];

        // Iterate over each character from right to left
        for (int l = n - 2; l >= 0; l--) {
            
            // This represents dp[l+1][h-1] from the previous row
            int prev = 0; 
            for (int h = l + 1; h < n; h++) {
                
                // Save current dp[h] before overwriting
                int temp = dp[h]; 
                
                if (s[l] == s[h]) {
                    
                    // No new insertion needed if characters match
                    dp[h] = prev; 
                } else {
                    
                    // Take min of two cases + 1
                    dp[h] = Math.Min(dp[h], dp[h - 1]) + 1; 
                }
                
                // Update prev for the next column
                prev = temp; 
            }
        }

        return dp[n - 1];
    }

    static void Main(string[] args) {
        string s = "geeks";
        Console.WriteLine(findMinInsertions(s));
    }
}
JavaScript
// JavaScript approach to find Minimum 
// insertions to form a palindrome

// Function to find minimum insertions 
// to make string palindrome
function findMinInsertions(s) {
    const n = s.length;
    const dp = new Array(n).fill(0);

    // Iterate over each character from right to left
    for (let l = n - 2; l >= 0; l--) {
        
        // This represents dp[l+1][h-1] from the previous row
        let prev = 0; 
        for (let h = l + 1; h < n; h++) {
            
            // Save current dp[h] before overwriting
            let temp = dp[h]; 
            
            if (s[l] === s[h]) {
                
                // No new insertion needed if characters match
                dp[h] = prev; 
            } else {
                
                // Take min of two cases + 1
                dp[h] = Math.min(dp[h], dp[h - 1]) + 1; 
            }
            
            // Update prev for the next column
            prev = temp; 
        }
    }

    return dp[n - 1];
}

const s = "geeks";
console.log(findMinInsertions(s));

Output
3

Related article: 


Next Article

Similar Reads