Minimum number of deletions to make a string palindrome
Given a string of size ‘n’. The task is to remove or delete the minimum number of characters from the string so that the resultant string is a palindrome.
Note: The order of characters should be maintained.
Examples :
Input : aebcbda
Output : 2
Remove characters 'e' and 'd'
Resultant string will be 'abcba'
which is a palindromic string
Input : geeksforgeeks
Output : 8
A simple solution is to remove all subsequences one by one and check if the remaining string is palindrome or not. The time complexity of this solution is exponential.
- Take two indexes first as ‘i’ and last as a ‘j’
- Compare the character at the index ‘i’ and ‘j’
- If characters are equal, then
- Recursively call the function by incrementing ‘i’ by ‘1’ and decrementing ‘j’ by ‘1’
- else
- Recursively call the two functions, the first increment ‘i’ by ‘1’ keeping ‘j’ constant, second decrement ‘j’ by ‘1’ keeping ‘i’ constant.
- Take a minimum of both and return by adding ‘1’
Below is the implementation of the above approach:
C++
#include <iostream>
using namespace std;
int min( int x, int y)
{
return (x < y) ? x : y;
}
int utility_fun_for_del(string str,
int i, int j)
{
if (i >= j)
return 0;
if (str[i] == str[j])
{
return utility_fun_for_del(str,
i + 1, j - 1);
}
return 1 + min(utility_fun_for_del(str, i + 1, j),
utility_fun_for_del(str, i, j - 1));
}
int min_ele_del(string str)
{
return utility_fun_for_del(str, 0,
str.length() - 1);
}
int main()
{
string str = "abefbac" ;
cout << "Minimum element of deletions = "
<< min_ele_del(str) << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG{
public static int min( int x, int y)
{
return (x < y) ? x : y;
}
public static int utility_fun_for_del(String str,
int i, int j)
{
if (i >= j)
return 0 ;
if (str.charAt(i) == str.charAt(j))
{
return utility_fun_for_del(str,
i + 1 , j - 1 );
}
return 1 + Math.min(utility_fun_for_del(str, i + 1 , j),
utility_fun_for_del(str, i, j - 1 ));
}
public static int min_ele_del(String str)
{
return utility_fun_for_del(str, 0 ,
str.length() - 1 );
}
public static void main(String[] args)
{
String str = "abefbac" ;
System.out.println( "Minimum element of deletions = " +
min_ele_del(str));
}
}
|
Python3
def utility_fun_for_del( Str , i, j):
if (i > = j):
return 0
if ( Str [i] = = Str [j]):
return utility_fun_for_del( Str , i + 1 ,
j - 1 )
return ( 1 + min (utility_fun_for_del( Str , i + 1 , j),
utility_fun_for_del( Str , i, j - 1 )))
def min_ele_del( Str ):
return utility_fun_for_del( Str , 0 ,
len ( Str ) - 1 )
Str = "abefbac"
print ( "Minimum element of deletions =" ,
min_ele_del( Str ))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int min( int x, int y)
{
return (x < y) ? x : y;
}
static int utility_fun_for_del( string str,
int i, int j)
{
if (i >= j)
return 0;
if (str[i] == str[j])
{
return utility_fun_for_del(str, i + 1,
j - 1);
}
return 1 + Math.Min(utility_fun_for_del(
str, i + 1, j),
utility_fun_for_del(
str, i, j - 1));
}
static int min_ele_del( string str)
{
return utility_fun_for_del(str, 0,
str.Length - 1);
}
static void Main()
{
string str = "abefbac" ;
Console.WriteLine( "Minimum element of " +
"deletions = " +
min_ele_del(str));
}
}
|
Javascript
<script>
function min(x, y)
{
return (x < y) ? x : y;
}
function utility_fun_for_del(str, i, j)
{
if (i >= j)
return 0;
if (str[i] == str[j])
{
return utility_fun_for_del(str, i + 1,
j - 1);
}
return 1 + Math.min(utility_fun_for_del(
str, i + 1, j),
utility_fun_for_del(
str, i, j - 1));
}
function min_ele_del(str)
{
return utility_fun_for_del(str, 0, str.length - 1);
}
let str = "abefbac" ;
document.write( "Minimum element of " +
"deletions = " +
min_ele_del(str));
</script>
|
Output
Minimum element of deletions = 2
Time complexity: O(2^n), the time complexity of this solution is exponential as it requires a recursive approach to solve the problem. There are two recursive calls in each step and hence the time complexity is O(2^n).
Auxiliary Space: O(n), the space complexity of this solution is linear as the recursive calls are stored in the stack frames and the maximum depth of the recursion tree can be n.
Approach: Top-down dynamic programming
Below is the implementation:
C++
#include<bits/stdc++.h>
using namespace std;
int dp[2000][2000];
int transformation(string s1, string s2,
int i, int j)
{
if (i >= (s1.size()) || j >= (s2.size()))
return 0;
if (s1[i] == s2[j])
{
dp[i][j] = 1 + transformation(s1, s2, i + 1,
j + 1);
}
if (dp[i][j] != -1)
{
return dp[i][j];
}
else
dp[i][j] = max(transformation(s1, s2, i, j + i),
transformation(s1, s2, i + 1, j));
return dp[s1.size() - 1][s2.size() - 1];
}
int main()
{
string s1 = "geeksforgeeks" ;
string s2 = "geeks" ;
int i = 0;
int j = 0;
memset (dp, -1, sizeof dp);
cout << "MINIMUM NUMBER OF DELETIONS: "
<< (s1.size()) - transformation(s1, s2, 0, 0)
<< endl;
cout << "MINIMUM NUMBER OF INSERTIONS: "
<< (s2.size()) - transformation(s1, s2, 0, 0)
<< endl;
cout << ( "LCS LENGTH: " )
<< transformation(s1, s2, 0, 0);
}
|
Java
import java.util.*;
public class GFG
{
static int dp[][] = new int [ 2000 ][ 2000 ];
public static int transformation(String s1,
String s2,
int i, int j)
{
if (i >= s1.length() || j >= s2.length())
{
return 0 ;
}
if (s1.charAt(i) == s2.charAt(j))
{
dp[i][j] = 1 + transformation(s1, s2, i + 1 , j + 1 );
}
if (dp[i][j] != - 1 )
{
return dp[i][j];
}
else
{
dp[i][j] = Math.max(transformation(s1, s2, i, j + i),
transformation(s1, s2, i + 1 , j));
}
return dp[s1.length() - 1 ][s2.length() - 1 ];
}
public static void main(String []args)
{
String s1 = "geeksforgeeks" ;
String s2 = "geeks" ;
int i = 0 ;
int j = 0 ;
for ( int [] row: dp)
{Arrays.fill(row, - 1 );}
System.out.println( "MINIMUM NUMBER OF DELETIONS: " +
(s1.length() - transformation(s1, s2, 0 , 0 )));
System.out.println( "MINIMUM NUMBER OF INSERTIONS: " +
(s2.length() - transformation(s1, s2, 0 , 0 )));
System.out.println( "LCS LENGTH: " +
transformation(s1, s2, 0 , 0 ));
}
}
|
Python3
def transformation(s1,s2,i,j,dp):
if i> = len (s1) or j> = len (s2):
return 0
if s1[i] = = s2[j]:
dp[i][j] = 1 + transformation(s1,s2,i + 1 ,j + 1 ,dp)
if dp[i][j]! = - 1 :
return dp[i][j]
else :
dp[i][j] = max (transformation(s1,s2,i,j + i,dp),
transformation(s1,s2,i + 1 ,j,dp))
return dp[ - 1 ][ - 1 ]
s1 = "geeksforgeeks"
s2 = "geeks"
i = 0
j = 0
dp = [[ - 1 for _ in range ( len (s1) + 1 )] for _ in range ( len (s2) + 1 )]
print ( "MINIMUM NUMBER OF DELETIONS: " ,
len (s1) - transformation(s1,s2, 0 , 0 ,dp),
end = " " )
print ( "MINIMUM NUMBER OF INSERTIONS: " ,
len (s2) - transformation(s1,s2, 0 , 0 ,dp),
end = " " )
print ( "LCS LENGTH: " ,transformation(s1,s2, 0 , 0 ,dp))
|
C#
using System;
class GFG{
static int [,] dp = new int [2000, 2000];
static int transformation( string s1, string s2,
int i, int j )
{
if (i >= (s1.Length) || j >= (s2.Length))
{
return 0;
}
if (s1[i] == s2[j])
{
dp[i, j] = 1 + transformation(s1, s2,
i + 1, j + 1);
}
if (dp[i, j] != -1)
{
return dp[i, j];
}
else
{
dp[i, j] = Math.Max(transformation(s1, s2, i,
j + i),
transformation(s1, s2,
i + 1, j));
}
return dp[s1.Length - 1, s2.Length - 1];
}
static public void Main()
{
string s1 = "geeksforgeeks" ;
string s2 = "geeks" ;
for ( int m = 0; m < 2000; m++ )
{
for ( int n = 0; n < 2000; n++)
{
dp[m, n] = -1;
}
}
Console.WriteLine( "MINIMUM NUMBER OF DELETIONS: " +
(s1.Length-transformation(s1, s2, 0, 0)));
Console.WriteLine( "MINIMUM NUMBER OF INSERTIONS: " +
(s2.Length-transformation(s1, s2, 0, 0)));
Console.WriteLine( "LCS LENGTH: " +
transformation(s1, s2, 0, 0));
}
}
|
Javascript
<script>
let dp = new Array(2000);
function transformation(s1, s2, i, j)
{
if (i >= s1.length || j >= s2.length)
{
return 0;
}
if (s1[i] == s2[j])
{
dp[i][j] = 1 + transformation(s1, s2, i + 1,
j + 1);
}
if (dp[i][j] != -1)
{
return dp[i][j];
}
else
{
dp[i][j] = Math.max(transformation(s1, s2, i, j + i),
transformation(s1, s2, i + 1, j));
}
return dp[s1.length - 1][s2.length - 1];
}
let s1 = "geeksforgeeks" ;
let s2 = "geeks" ;
let i = 0;
let j = 0;
for (let row = 0; row < dp.length; row++)
{
dp[row] = new Array(dp.length);
for (let column = 0;
column < dp.length;
column++)
{
dp[row][column] = -1;
}
}
document.write( "MINIMUM NUMBER OF DELETIONS: " +
(s1.length - transformation(s1, s2, 0, 0)));
document.write( " MINIMUM NUMBER OF INSERTIONS: " +
(s2.length - transformation(s1, s2, 0, 0)));
document.write( " LCS LENGTH: " +
transformation(s1, s2, 0, 0));
</script>
|
Output:
MINIMUM NUMBER OF DELETIONS: 8 MINIMUM NUMBER OF INSERTIONS: 0 LCS LENGTH: 5
Time Complexity: O(N^K)
Auxiliary Space: O(2000*2000)
Efficient Approach: It uses the concept of finding the length of the longest palindromic subsequence of a given sequence.
Below is the implementation of the approach:
C++
#include <bits/stdc++.h>
using namespace std;
int lps(string str)
{
int n = str.size();
int L[n][n];
for ( int i = 0; i < n; i++)
L[i][i] = 1;
for ( int cl = 2; cl <= n; cl++)
{
for ( int i = 0;
i < n - cl + 1; i++)
{
int j = i + cl - 1;
if (str[i] == str[j] &&
cl == 2)
L[i][j] = 2;
else if (str[i] == str[j])
L[i][j] = L[i + 1][j - 1] + 2;
else
L[i][j] = max(L[i][j - 1],
L[i + 1][j]);
}
}
return L[0][n - 1];
}
int minimumNumberOfDeletions(string str)
{
int n = str.size();
int len = lps(str);
return (n - len);
}
int main()
{
string str = "geeksforgeeks" ;
cout << "Minimum number of deletions = "
<< minimumNumberOfDeletions(str);
return 0;
}
|
Java
class GFG
{
static int lps(String str)
{
int n = str.length();
int L[][] = new int [n][n];
for ( int i = 0 ; i < n; i++)
L[i][i] = 1 ;
for ( int cl = 2 ; cl <= n; cl++)
{
for ( int i = 0 ; i < n - cl + 1 ; i++)
{
int j = i + cl - 1 ;
if (str.charAt(i) ==
str.charAt(j) && cl == 2 )
L[i][j] = 2 ;
else if (str.charAt(i) ==
str.charAt(j))
L[i][j] = L[i + 1 ][j - 1 ] + 2 ;
else
L[i][j] = Integer.max(L[i][j - 1 ],
L[i + 1 ][j]);
}
}
return L[ 0 ][n - 1 ];
}
static int minimumNumberOfDeletions(String str)
{
int n = str.length();
int len = lps(str);
return (n - len);
}
public static void main(String[] args)
{
String str = "geeksforgeeks" ;
System.out.println( "Minimum number " +
"of deletions = " +
minimumNumberOfDeletions(str));
}
}
|
Python3
def lps( str ):
n = len ( str )
L = [[ 0 for x in range (n)] for y in range (n)]
for i in range (n):
L[i][i] = 1
for cl in range ( 2 , n + 1 ):
for i in range (n - cl + 1 ):
j = i + cl - 1
if ( str [i] = = str [j] and cl = = 2 ):
L[i][j] = 2
elif ( str [i] = = str [j]):
L[i][j] = L[i + 1 ][j - 1 ] + 2
else :
L[i][j] = max (L[i][j - 1 ],L[i + 1 ][j])
return L[ 0 ][n - 1 ]
def minimumNumberOfDeletions( str ):
n = len ( str )
l = lps( str )
return (n - l)
if __name__ = = "__main__" :
str = "geeksforgeeks"
print ( "Minimum number of deletions = "
, minimumNumberOfDeletions( str ))
|
C#
using System;
class GFG
{
static int lps(String str)
{
int n = str.Length;
int [,]L = new int [n, n];
for ( int i = 0; i < n; i++)
L[i, i] = 1;
for ( int cl = 2; cl <= n; cl++)
{
for ( int i = 0; i < n - cl + 1; i++)
{
int j = i + cl - 1;
if (str[i] == str[j] && cl == 2)
L[i, j] = 2;
else if (str[i] == str[j])
L[i, j] = L[i + 1, j - 1] + 2;
else
L[i, j] = Math.Max(L[i, j - 1],
L[i + 1, j]);
}
}
return L[0, n - 1];
}
static int minimumNumberOfDeletions( string str)
{
int n = str.Length;
int len = lps(str);
return (n - len);
}
public static void Main()
{
string str = "geeksforgeeks" ;
Console.Write( "Minimum number of" +
" deletions = " +
minimumNumberOfDeletions(str));
}
}
|
Javascript
<script>
function lps(str)
{
let n = str.length;
let L = new Array(n);
for (let i = 0; i < n; i++)
{
L[i] = new Array(n);
for (let j = 0; j < n; j++)
{
L[i][j] = 0;
}
}
for (let i = 0; i < n; i++)
L[i][i] = 1;
for (let cl = 2; cl <= n; cl++)
{
for (let i = 0; i < n - cl + 1; i++)
{
let j = i + cl - 1;
if (str[i] == str[j] && cl == 2)
L[i][j] = 2;
else if (str[i] == str[j])
L[i][j] = L[i + 1][j - 1] + 2;
else
L[i][j] = Math.max(L[i][j - 1], L[i + 1][j]);
}
}
return L[0][n - 1];
}
function minimumNumberOfDeletions(str)
{
let n = str.length;
let len = lps(str);
return (n - len);
}
let str = "geeksforgeeks" ;
document.write( "Minimum number " + "of deletions = " +
minimumNumberOfDeletions(str));
</script>
|
PHP
<?php
function lps( $str )
{
$n = strlen ( $str );
$L ;
for ( $i = 0; $i < $n ; $i ++)
$L [ $i ][ $i ] = 1;
for ( $cl = 2; $cl <= $n ; $cl ++)
{
for ( $i = 0;
$i < $n - $cl + 1;
$i ++)
{
$j = $i + $cl - 1;
if ( $str [ $i ] == $str [ $j ] &&
$cl == 2)
$L [ $i ][ $j ] = 2;
else if ( $str [ $i ] == $str [ $j ])
$L [ $i ][ $j ] =
$L [ $i + 1][ $j - 1] + 2;
else
$L [ $i ][ $j ] = max( $L [ $i ][ $j - 1],
$L [ $i + 1][ $j ]);
}
}
return $L [0][ $n - 1];
}
function minimumNumberOfDeletions( $str )
{
$n = strlen ( $str );
$len = lps( $str );
return ( $n - $len );
}
{
$str = "geeksforgeeks" ;
echo "Minimum number of deletions = " ,
minimumNumberOfDeletions( $str );
return 0;
}
?>
|
Output
Minimum number of deletions = 8
Time Complexity: O(n^2),as the LPS subproblem is solved using dynamic programming.
Auxiliary Space: O(n^2) as a 2D array of size nxn is used to store the subproblems.
Efficient Approach: Space optimization
In the previous approach, the current value dp[i][j] only depends upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int lps(string str)
{
int n = str.size();
int L[n];
for ( int i = n - 1; i >= 0; i--)
{
int back_up = 0;
for ( int j = i; j < n; j++)
{
if (j == i)
L[j] = 1;
else if (str[i] == str[j])
{
int temp = L[j];
L[j] = back_up + 2;
back_up = temp;
}
else
{
back_up = L[j];
L[j] = max(L[j], L[j - 1]);
}
}
}
return L[n - 1];
}
int minimumNumberOfDeletions(string str)
{
int n = str.size();
int len = lps(str);
return (n - len);
}
int main()
{
string str = "geeksforgeeks" ;
cout << "Minimum number of deletions = " << minimumNumberOfDeletions(str);
return 0;
}
|
Java
public class Main {
static int lps(String str) {
int n = str.length();
int [] L = new int [n];
for ( int i = n - 1 ; i >= 0 ; i--) {
int back_up = 0 ;
for ( int j = i; j < n; j++) {
if (j == i)
L[j] = 1 ;
else if (str.charAt(i) == str.charAt(j)) {
int temp = L[j];
L[j] = back_up + 2 ;
back_up = temp;
} else {
back_up = L[j];
L[j] = Math.max(L[j], L[j - 1 ]);
}
}
}
return L[n - 1 ];
}
static int minimumNumberOfDeletions(String str) {
int n = str.length();
int len = lps(str);
return (n - len);
}
public static void main(String[] args) {
String str = "geeksforgeeks" ;
System.out.println( "Minimum number of deletions = " + minimumNumberOfDeletions(str));
}
}
|
Python3
def lps(string):
n = len (string)
L = [ 0 ] * n
for i in range (n - 1 , - 1 , - 1 ):
back_up = 0
for j in range (i, n):
if j = = i:
L[j] = 1
elif string[i] = = string[j]:
temp = L[j]
L[j] = back_up + 2
back_up = temp
else :
back_up = L[j]
L[j] = max (L[j], L[j - 1 ])
return L[n - 1 ]
def minimumNumberOfDeletions(string):
n = len (string)
length = lps(string)
return (n - length)
if __name__ = = "__main__" :
string = "geeksforgeeks"
print ( "Minimum number of deletions =" , minimumNumberOfDeletions(string))
|
C#
using System;
class Program
{
static int LPS( string str)
{
int n = str.Length;
int [] L = new int [n];
for ( int i = n - 1; i >= 0; i--)
{
int back_up = 0;
for ( int j = i; j < n; j++)
{
if (j == i)
L[j] = 1;
else if (str[i] == str[j])
{
int temp = L[j];
L[j] = back_up + 2;
back_up = temp;
}
else
{
back_up = L[j];
L[j] = Math.Max(L[j], L[j - 1]);
}
}
}
return L[n - 1];
}
static int MinimumNumberOfDeletions( string str)
{
int n = str.Length;
int len = LPS(str);
return (n - len);
}
static void Main()
{
string str = "geeksforgeeks" ;
Console.WriteLine( "Minimum number of deletions = " + MinimumNumberOfDeletions(str));
}
}
|
Javascript
function lps(str) {
const n = str.length;
const L = new Array(n).fill(0);
for (let i = n - 1; i >= 0; i--) {
let back_up = 0;
for (let j = i; j < n; j++) {
if (j === i) {
L[j] = 1;
} else if (str[i] === str[j]) {
const temp = L[j];
L[j] = back_up + 2;
back_up = temp;
} else {
back_up = L[j];
L[j] = Math.max(L[j], L[j - 1]);
}
}
}
return L[n - 1];
}
function minimumNumberOfDeletions(str) {
const n = str.length;
const len = lps(str);
return n - len;
}
const str = "geeksforgeeks" ;
console.log( "Minimum number of deletions =" , minimumNumberOfDeletions(str));
|
Output
Minimum number of deletions = 8
Time Complexity: O(n^2).
Auxiliary Space: O(n)
Another Efficient approach: (Bottom-Up Approach) Also, we can directly compute the minimum number of deletions directly from a single function. We can intuitively come up by computing minimum number of deletions for smaller substrings first. Below is the code implementation for the approach.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int minimumNumberOfDeletions(string s)
{
int n = s.length();
vector< int > dp(n);
for ( int i = n - 2; i >= 0; i--) {
int prev = 0;
for ( int j = i + 1; j < n; j++) {
int temp = dp[j];
if (s[i] == s[j]) {
dp[j] = prev;
} else {
dp[j] = min(dp[j], dp[j-1]) + 1;
}
prev = temp;
}
}
return dp[n-1];
}
int main()
{
string str = "geeksforgeeks" ;
cout << "Minimum number of deletions = " << minimumNumberOfDeletions(str);
return 0;
}
|
Java
import java.util.Arrays;
public class MinimumDeletionsPalindrome {
static int minimumNumberOfDeletions(String s) {
int n = s.length();
int [] dp = new int [n];
for ( int i = n - 2 ; i >= 0 ; i--) {
int prev = 0 ;
for ( int j = i + 1 ; j < n; j++) {
int temp = dp[j];
if (s.charAt(i) == s.charAt(j)) {
dp[j] = prev;
} else {
dp[j] = Math.min(dp[j], dp[j - 1 ]) + 1 ;
}
prev = temp;
}
}
return dp[n - 1 ];
}
public static void main(String[] args) {
String str = "geeksforgeeks" ;
System.out.println( "Minimum number of deletions = " + minimumNumberOfDeletions(str));
}
}
|
Python
def minimum_number_of_deletions(s):
n = len (s)
dp = [ 0 ] * n
for i in range (n - 2 , - 1 , - 1 ):
prev = 0
for j in range (i + 1 , n):
temp = dp[j]
if s[i] = = s[j]:
dp[j] = prev
else :
dp[j] = min (dp[j], dp[j - 1 ]) + 1
prev = temp
return dp[n - 1 ]
if __name__ = = "__main__" :
str_input = "geeksforgeeks"
print ( "Minimum number of deletions =" , minimum_number_of_deletions(str_input))
|
C#
using System;
class GFG {
static int MinimumNumberOfDeletions( string s)
{
int n = s.Length;
int [] dp = new int [n];
for ( int i = n - 2; i >= 0; i--) {
int prev = 0;
for ( int j = i + 1; j < n; j++) {
int temp = dp[j];
if (s[i] == s[j]) {
dp[j] = prev;
}
else {
dp[j] = Math.Min(dp[j], dp[j - 1]) + 1;
}
prev = temp;
}
}
return dp[n - 1];
}
static void Main()
{
string str = "geeksforgeeks" ;
Console.WriteLine( "Minimum number of deletions = "
+ MinimumNumberOfDeletions(str));
}
}
|
Javascript
function minimumNumberOfDeletions(s) {
let n = s.length;
let dp = new Array(n).fill(0);
for (let i = n - 2; i >= 0; i--) {
let prev = 0;
for (let j = i + 1; j < n; j++) {
let temp = dp[j];
if (s[i] == s[j]) {
dp[j] = prev;
} else {
dp[j] = Math.min(dp[j], dp[j - 1]) + 1;
}
prev = temp;
}
}
return dp[n - 1];
}
let str = "geeksforgeeks" ;
console.log( "Minimum number of deletions = " + minimumNumberOfDeletions(str));
|
Output:
Minimum number of deletions = 8
Time Complexity: O(n^2).
Auxiliary Space: O(n)
Last Updated :
20 Dec, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...