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>
|
OutputMinimum 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;
}
?>
|
OutputMinimum 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;
}
|
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));
|
OutputMinimum number of deletions = 8
Time Complexity: O(n^2).
Auxiliary Space: O(n)
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.