Minimum steps to delete a string

Last Updated : 17 May, 2026

Given a string s of size n consisting of digits only, find the minimum number of steps required to delete the entire string. In one step, you can delete any substring of s that is a palindrome. After deletion, the remaining parts of the string are concatenated.

Examples:

Input: s = "2553432"
Output: 2
Explanation: In the first step, remove "55", after which the string becomes "23432", which is a palindrome and can be removed in the second step.

Input: s = "1234"
Output: 4
Explanation: Each character is removed individually since no longer palindromic substring exist.

Try It Yourself
redirect icon

[Naive Approach] - Using Recursion - Exponential Time

The idea is to solve the problem recursively by trying all possible ways to delete the current substring and taking the minimum operations among them.

For every substring str[start...end]:

  • First, delete the first character separately and recursively solve the remaining substring.
  • If the first two characters are same, delete them together since they form a palindrome of length 2.
  • Search for another occurrence of the first character later in the string. If found, both matching characters can be deleted as part of the same palindrome, so recursively solve the middle and remaining right parts.
  • By exploring all possible deletions and choosing the minimum answer, we get the minimum operations required to delete the entire string.

Consider the string: s= "2553432". We start from the first character and try all possible choices.

  • First, we can delete '2' separately and recursively solve "553432".
  • Next, we check whether the first two characters are same, but '2' and '5' are different, so this option is skipped.
  • Then, we search for another '2' later in the string and find it at the last index. 2 5 5 3 4 3 2
  • Now the problem is divided into: middle substring "55343" and remaining right substring ""
  • For "55343", the first two characters "55" are same, so we delete them together in one operation. The remaining string becomes "343", which is a palindrome and can be deleted in one more operation.
  • Thus, the total operations required are: "55" -> 1 operation and "343" -> 1 operation

So, the minimum operations needed to delete the string are: 2

C++
#include <bits/stdc++.h>
using namespace std;

int solve(string &str, int start, int end) {

    // if string is empty
    if (start > end)
        return 0;

    // if string has one character
    if (start == end)
        return 1;

    // if string has two same characters
    if (start + 1 == end && str[start] == str[end])
        return 1;

    // delete first character separately
    int res = 1 + solve(str, start + 1, end);

    // if first two characters are same
    if (str[start] == str[start + 1])
        res = min(res, 1 + solve(str, start + 2, end));

    // match first character with same character later
    for (int i = start + 2; i <= end; i++) {
        if (str[start] == str[i]) {
            res = min(res, solve(str, start + 1, i - 1) + solve(str, i + 1, end));
        }
    }

    return res;
}

int minStepToDeleteString(string &str) {
    return solve(str, 0, str.size() - 1);
}

int main() {

    string str = "2553432";

    cout << minStepToDeleteString(str);

    return 0;
}
Java
class GFG {

    static int solve(String str, int start, int end) {

        // if string is empty
        if (start > end)
            return 0;

        // if string has one character
        if (start == end)
            return 1;

        // if string has two same characters
        if (start + 1 == end && str.charAt(start) == str.charAt(end))
            return 1;

        // delete first character separately
        int res = 1 + solve(str, start + 1, end);

        // if first two characters are same
        if (str.charAt(start) == str.charAt(start + 1))
            res = Math.min(res,
                           1 + solve(str, start + 2, end));

        // match first character with same character later
        for (int i = start + 2; i <= end; i++) {
            if (str.charAt(start) == str.charAt(i)) {
                res = Math.min(res, solve(str, start + 1, i - 1) + solve(str, i + 1, end));
            }
        }

        return res;
    }

    static int minStepToDeleteString(String str) {
        return solve(str, 0, str.length() - 1);
    }

    public static void main(String[] args) {

        String str = "2553432";

        System.out.println(minStepToDeleteString(str));
    }
}
Python
def solve(str, start, end):

    # if string is empty
    if start > end:
        return 0

    # if string has one character
    if start == end:
        return 1

    # if string has two same characters
    if start + 1 == end and str[start] == str[end]:
        return 1

    # delete first character separately
    res = 1 + solve(str, start + 1, end)

    # if first two characters are same
    if str[start] == str[start + 1]:
        res = min(res,
                  1 + solve(str, start + 2, end))

    # match first character with same character later
    for i in range(start + 2, end + 1):
        if str[start] == str[i]:
            res = min(res,
                      solve(str, start + 1, i - 1) +
                      solve(str, i + 1, end))

    return res


def minStepToDeleteString(str):
    return solve(str, 0, len(str) - 1)


str = "2553432"

print(minStepToDeleteString(str))
C#
using System;

class GFG {

    static int solve(string str, int start, int end) {

        // if string is empty
        if (start > end)
            return 0;

        // if string has one character
        if (start == end)
            return 1;

        // if string has two same characters
        if (start + 1 == end && str[start] == str[end])
            return 1;

        // delete first character separately
        int res = 1 + solve(str, start + 1, end);

        // if first two characters are same
        if (str[start] == str[start + 1])
            res = Math.Min(res,
                           1 + solve(str, start + 2, end));

        // match first character with same character later
        for (int i = start + 2; i <= end; i++) {
            if (str[start] == str[i]) {
                res = Math.Min(res, solve(str, start + 1, i - 1) + solve(str, i + 1, end));
            }
        }

        return res;
    }

    static int minStepToDeleteString(string str) {
        return solve(str, 0, str.Length - 1);
    }

    static void Main() {

        string str = "2553432";

        Console.WriteLine(minStepToDeleteString(str));
    }
}
JavaScript
function solve(str, start, end) {

    // if string is empty
    if (start > end)
        return 0;

    // if string has one character
    if (start === end)
        return 1;

    // if string has two same characters
    if (start + 1 === end && str[start] === str[end])
        return 1;

    // delete first character separately
    let res = 1 + solve(str, start + 1, end);

    // if first two characters are same
    if (str[start] === str[start + 1])
        res = Math.min(res,
                       1 + solve(str, start + 2, end));

    // match first character with same character later
    for (let i = start + 2; i <= end; i++) {
        if (str[start] === str[i]) {
            res = Math.min(res,solve(str, start + 1, i - 1) + solve(str, i + 1, end));
        }
    }

    return res;
}

function minStepToDeleteString(str) {
    return solve(str, 0, str.length - 1);
}

// Drive code
let str = "2553432";
console.log(minStepToDeleteString(str));

Output
2

[Expected Approach] - Using Memoization - O(n ^ 3) Time and O(n ^ 2) Space

In the recursive approach, the same substring is solved again and again, which makes the solution slow. To avoid this, we use memoization.

We create a 2D array memo[][] to store the minimum operations needed for every substring str[i...j]. Before solving any substring, we first check whether its answer is already stored in memo[][]. If it is already present, we directly return that value instead of calculating it again.

  • Create a 2D array memo[][] of size n x n initialized with -1.
  • Define a recursive function for substring str[i...j].
  • If the substring is empty, return 0.
  • If the substring has one character, return 1.
  • Delete the first character separately and solve the remaining substring.
  • If the first two characters are same, delete them together.
  • Search for another occurrence of the first character later in the string and solve the middle and remaining right parts.
  • Store the minimum answer in memo[i][j].
  • Return memo[0][n-1] as the final answer.
C++
#include <bits/stdc++.h>
using namespace std;

// Recursive function to find the minimum
// operations required to delete a string
int solve(string &str, int start, int end, vector<vector<int>> &memo) {

    // if the string is empty no operations required
    if (start > end)
        return 0;

    // if the string has only one character
    // one operation required
    if (start == end)
        return 1;

    // if string has only two characters
    // and both the characters are same
    if (start + 1 == end && str[start] == str[end])
        return 1;

    // if result is already calculated
    if (memo[start][end] != -1)
        return memo[start][end];

    // delete first character separately
    int res = 1 + solve(str, start + 1, end, memo);

    // if first two characters are same
    if (str[start] == str[start + 1])
        res = min(res, 1 + solve(str, start + 2, end, memo));

    // match first character with same character later
    for (int i = start + 2; i <= end; i++) {

        if (str[start] == str[i]) {

            res = min(res,
                      solve(str, start + 1, i - 1, memo) +
                      solve(str, i + 1, end, memo));
        }
    }

    return memo[start][end] = res;
}

// Function to find the minimum operations
// to delete the string entirely
int minStepToDeleteString(string str) {

    int n = str.size();

    // to store results of subproblems
    vector<vector<int>> memo(n, vector<int>(n, -1));

    return solve(str, 0, n - 1, memo);
}

int main() {

    string str = "2553432";

    cout << minStepToDeleteString(str);

    return 0;
}
Java
import java.util.Arrays;

class GFG {

    // Recursive function to find the minimum
    // operations required to delete a string
    static int solve(String str, int start, int end,
                     int[][] memo) {

        // if the string is empty
        // no operations required
        if (start > end)
            return 0;

        // if the string has only one character
        // one operation required
        if (start == end)
            return 1;

        // if string has only two characters
        // and both the characters are same
        if (start + 1 == end &&str.charAt(start) == str.charAt(end))
            return 1;

        // if result is already calculated
        if (memo[start][end] != -1)
            return memo[start][end];

        // delete first character separately
        int res = 1 + solve(str, start + 1, end, memo);

        // if first two characters are same
        if (str.charAt(start) == str.charAt(start + 1))
            res = Math.min(res, 1 + solve(str, start + 2, end, memo));

        // match first character with same character later
        for (int i = start + 2; i <= end; i++) {

            if (str.charAt(start) == str.charAt(i)) {

                res = Math.min(res,
                               solve(str, start + 1, i - 1, memo) +
                               solve(str, i + 1, end, memo));
            }
        }

        return memo[start][end] = res;
    }

    // Function to find the minimum operations
    // to delete the string entirely
    static int minStepToDeleteString(String str) {

        int n = str.length();

        // to store results of subproblems
        int[][] memo = new int[n][n];

        for (int i = 0; i < n; i++) {
            Arrays.fill(memo[i], -1);
        }

        return solve(str, 0, n - 1, memo);
    }

    public static void main(String[] args) {

        String str = "2553432";

        System.out.println(minStepToDeleteString(str));
    }
}
Python
# Recursive function to find the minimum
# operations required to delete a string
def solve(str, start, end, memo):

    # if the string is empty
    # no operations required
    if start > end:
        return 0

    # if the string has only one character
    # one operation required
    if start == end:
        return 1

    # if string has only two characters
    # and both the characters are same
    if start + 1 == end and str[start] == str[end]:
        return 1

    # if result is already calculated
    if memo[start][end] != -1:
        return memo[start][end]

    # delete first character separately
    res = 1 + solve(str, start + 1, end, memo)

    # if first two characters are same
    if str[start] == str[start + 1]:
        res = min(res, 1 + solve(str, start + 2, end, memo))

    # match first character with same character later
    for i in range(start + 2, end + 1):

        if str[start] == str[i]:

            res = min(res,
                      solve(str, start + 1, i - 1, memo) +
                      solve(str, i + 1, end, memo))

    memo[start][end] = res
    return res


# Function to find the minimum operations
# to delete the string entirely
def minStepToDeleteString(str):

    n = len(str)

    # to store results of subproblems
    memo = [[-1 for _ in range(n)] for _ in range(n)]

    return solve(str, 0, n - 1, memo)


if __name__ == "__main__":

    str = "2553432"

    print(minStepToDeleteString(str))
C#
using System;

class GFG {

    // Recursive function to find the minimum
    // operations required to delete a string
    static int solve(string str, int start, int end, int[,] memo) {

        // if the string is empty
        // no operations required
        if (start > end)
            return 0;

        // if the string has only one character
        // one operation required
        if (start == end)
            return 1;

        // if string has only two characters
        // and both the characters are same
        if (start + 1 == end && str[start] == str[end])
            return 1;

        // if result is already calculated
        if (memo[start, end] != -1)
            return memo[start, end];

        // delete first character separately
        int res = 1 + solve(str, start + 1, end, memo);

        // if first two characters are same
        if (str[start] == str[start + 1])
            res = Math.Min(res, 1 + solve(str, start + 2, end, memo));

        // match first character with same character later
        for (int i = start + 2; i <= end; i++) {

            if (str[start] == str[i]) {

                res = Math.Min(res,
                               solve(str, start + 1, i - 1, memo) +
                               solve(str, i + 1, end, memo));
            }
        }

        memo[start, end] = res;
        return res;
    }

    // Function to find the minimum operations
    // to delete the string entirely
    static int minStepToDeleteString(string str) {

        int n = str.Length;

        // to store results of subproblems
        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 solve(str, 0, n - 1, memo);
    }

    static void Main() {

        string str = "2553432";

        Console.WriteLine(minStepToDeleteString(str));
    }
}
JavaScript
// Recursive function to find the minimum
// operations required to delete a string
function solve(str, start, end, memo) {

    // if the string is empty
    // no operations required
    if (start > end)
        return 0;

    // if the string has only one character
    // one operation required
    if (start === end)
        return 1;

    // if string has only two characters
    // and both the characters are same
    if (start + 1 === end && str[start] === str[end])
        return 1;

    // if result is already calculated
    if (memo[start][end] !== -1)
        return memo[start][end];

    // delete first character separately
    let res = 1 + solve(str, start + 1, end, memo);

    // if first two characters are same
    if (str[start] === str[start + 1])
        res = Math.min(res, 1 + solve(str, start + 2, end, memo));

    // match first character with same character later
    for (let i = start + 2; i <= end; i++) {

        if (str[start] === str[i]) {

            res = Math.min(res,
                           solve(str, start + 1, i - 1, memo) +
                           solve(str, i + 1, end, memo));
        }
    }

    memo[start][end] = res;
    return res;
}

// Function to find the minimum operations
// to delete the string entirely
function minStepToDeleteString(str) {

    let n = str.length;

    // to store results of subproblems
    let memo = Array.from({ length: n }, () => Array(n).fill(-1));

    return solve(str, 0, n - 1, memo);
}

// Drive code
let str = "2553432";
console.log(minStepToDeleteString(str));

Output
2

[Expected Approach - 2] - Using Tabulation - O(n ^ 3) Time and O(n ^ 2) Space

The idea is to solve the problem using dynamic programming by building a 2D table dp[][] where each entry dp[i][j] represents the minimum operations required to delete the substring s[i..j]. We calculate these values by considering the deletion of a single character, deleting two consecutive identical characters together, and combining the results from splitting at positions where the current character reoccurs.

  • Create a 2D array dp[][] of size n x n.
  • Traverse all substring lengths from 1 to n.
  • If substring length is 1, set dp[i][j] = 1.
  • Otherwise, first delete the current character separately.
  • If the first two characters are same, delete them together.
  • Search for another occurrence of the current character later in the string and update the minimum answer.
  • Finally, return dp[0][n-1] as the minimum operations required to delete the entire string.

Consider the string: s= "2553432". We create a DP table dp[][] where dp[i][j] stores the minimum operations required to delete substring str[i...j].

  • Length = 1: Every single character needs one operation. dp[i][i] = 1
  • Length = 2: For substring "55": Both characters are same, so: dp[1][2] = 1 because "55" can be deleted together.
  • Length = 3: For substring "343": First and last characters are same, so "343" can be deleted in one operation. dp[3][5] = 1.
  • Length = 5: For substring "55343": Delete "55" together and then Remaining substring "343" already takes one operation. So: dp[1][5] = 2.
  • Full String: For substring "2553432": First and last characters are same. so middle substring "55343" already requires 2 operations, so the whole string can also be deleted in: 2 operations.

Hence, the minimum operations required are: 2

C++
#include <bits/stdc++.h>
using namespace std;

int minStepToDeleteString(string &str) {

    int n = str.size();

    // dp[i][j] stores minimum operations
    // required to delete substring str[i...j]
    vector<vector<int>> dp(n + 1,
                           vector<int>(n + 1, 0));

    // traverse all substring lengths
    for (int len = 1; len <= n; len++) {

        // generate all substrings of length len
        for (int i = 0, j = len - 1; j < n; i++, j++) {

            // single character needs one operation
            if (len == 1) {
                dp[i][j] = 1;
                continue;
            }

            // delete current character separately
            dp[i][j] = 1 + dp[i + 1][j];

            // if first two characters are same,
            // delete them together
            if (str[i] == str[i + 1]) {

                dp[i][j] = min(dp[i][j],
                               1 + dp[i + 2][j]);
            }

            // match current character with same
            // character later in the string
            for (int k = i + 2; k <= j; k++) {

                if (str[i] == str[k]) {

                    dp[i][j] = min(dp[i][j],
                                   dp[i + 1][k - 1] +
                                   dp[k + 1][j]);
                }
            }
        }
    }

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

int main() {

    string str = "2553432";
    cout << minStepToDeleteString(str);

    return 0;
}
Java
import java.util.Arrays;

class GFG {

    static public int minStepToDeleteString(String str) {

        int n = str.length();

        // dp[i][j] stores minimum operations
        // required to delete substring str[i...j]
        int[][] dp = new int[n + 1][n + 1];

        // traverse all substring lengths
        for (int len = 1; len <= n; len++) {

            // generate all substrings of length len
            for (int i = 0, j = len - 1; j < n; i++, j++) {

                // single character needs one operation
                if (len == 1) {
                    dp[i][j] = 1;
                    continue;
                }

                // delete current character separately
                dp[i][j] = 1 + dp[i + 1][j];

                // if first two characters are same,
                // delete them together
                if (str.charAt(i) == str.charAt(i + 1)) {

                    dp[i][j] = Math.min(dp[i][j],
                                        1 + dp[i + 2][j]);
                }

                // match current character with same
                // character later in the string
                for (int k = i + 2; k <= j; k++) {

                    if (str.charAt(i) == str.charAt(k)) {

                        dp[i][j] = Math.min(dp[i][j],
                                            dp[i + 1][k - 1] +
                                            dp[k + 1][j]);
                    }
                }
            }
        }

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

    public static void main(String[] args) {

        String str = "2553432";
        System.out.println(minStepToDeleteString(str));
    }
}
Python
def minStepToDeleteString(str):

    n = len(str)

    # dp[i][j] stores minimum operations
    # required to delete substring str[i...j]
    dp = [[0 for _ in range(n + 1)]
             for _ in range(n + 1)]

    # traverse all substring lengths
    for length in range(1, n + 1):

        # generate all substrings of length length
        i = 0
        j = length - 1

        while j < n:

            # single character needs one operation
            if length == 1:
                dp[i][j] = 1

            else:

                # delete current character separately
                dp[i][j] = 1 + dp[i + 1][j]

                # if first two characters are same,
                # delete them together
                if str[i] == str[i + 1]:

                    dp[i][j] = min(dp[i][j],
                                   1 + dp[i + 2][j])

                # match current character with same
                # character later in the string
                for k in range(i + 2, j + 1):

                    if str[i] == str[k]:

                        dp[i][j] = min(dp[i][j],
                                       dp[i + 1][k - 1] +
                                       dp[k + 1][j])

            i += 1
            j += 1

    return dp[0][n - 1]


if __name__ == "__main__":

    str = "2553432"

    print(minStepToDeleteString(str))
C#
using System;

public class GFG {

    public static int minStepToDeleteString(string str) {

        int n = str.Length;

        // dp[i][j] stores minimum operations
        // required to delete substring str[i...j]
        int[,] dp = new int[n + 1, n + 1];

        // traverse all substring lengths
        for (int len = 1; len <= n; len++) {

            // generate all substrings of length len
            for (int i = 0, j = len - 1; j < n; i++, j++) {

                // single character needs one operation
                if (len == 1) {
                    dp[i, j] = 1;
                    continue;
                }

                // delete current character separately
                dp[i, j] = 1 + dp[i + 1, j];

                // if first two characters are same,
                // delete them together
                if (str[i] == str[i + 1]) {

                    dp[i, j] = Math.Min(dp[i, j],
                                        1 + dp[i + 2, j]);
                }

                // match current character with same
                // character later in the string
                for (int k = i + 2; k <= j; k++) {

                    if (str[i] == str[k]) {

                        dp[i, j] = Math.Min(dp[i, j],
                                            dp[i + 1, k - 1] +
                                            dp[k + 1, j]);
                    }
                }
            }
        }

        return dp[0, n - 1];
    }

    public static void Main() {

        string str = "2553432";

        Console.WriteLine(minStepToDeleteString(str));
    }
}
JavaScript
function minStepToDeleteString(str) {

    let n = str.length;

    // dp[i][j] stores minimum operations
    // required to delete substring str[i...j]
    let dp = Array.from({ length: n + 1 },
             () => Array(n + 1).fill(0));

    // traverse all substring lengths
    for (let len = 1; len <= n; len++) {

        // generate all substrings of length len
        for (let i = 0, j = len - 1; j < n; i++, j++) {

            // single character needs one operation
            if (len === 1) {
                dp[i][j] = 1;
                continue;
            }

            // delete current character separately
            dp[i][j] = 1 + dp[i + 1][j];

            // if first two characters are same,
            // delete them together
            if (str[i] === str[i + 1]) {

                dp[i][j] = Math.min(dp[i][j],
                                    1 + dp[i + 2][j]);
            }

            // match current character with same
            // character later in the string
            for (let k = i + 2; k <= j; k++) {

                if (str[i] === str[k]) {

                    dp[i][j] = Math.min(dp[i][j],
                                        dp[i + 1][k - 1] +
                                        dp[k + 1][j]);
                }
            }
        }
    }

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

// Drive code
let str = "2553432";
console.log(minStepToDeleteString(str));

Output
2
Comment