Recursively remove all adjacent duplicates (original) (raw)

Last Updated : 21 May, 2026

Given a string **s, remove all its adjacent duplicate characters recursively.

**Examples:

**Input: s = "geeksforgeek"
**Output: "gksforgk"
**Explanation: g(ee)ksforg(ee)k -> gksforgk

**Input: s = "abccbccba"
**Output: ""
**Explanation: ab(cc)b(cc)ba->abbba->a(bbb)a->aa->(aa)->"" (empty string)

Try It Yourselfredirect icon

Table of Content

[Naive Approach] Using Recursion - O(n ^ 2) Time and O(n ^ 2) Space

The idea is to first iteratively build a new string in **result by removing adjacent duplicates. After one full pass, if the length of the string of **result remains as original string, returns the **result. If changes were made (meaning some duplicates were removed), simply calls itself recursively on the newly formed string. This ensures that any new adjacent duplicates formed by the removal of previous ones are also eliminated. The idea is to gradually "peel off" the duplicates layer by layer until no adjacent duplicates are left.

C++ `

#include using namespace std;

// Function to recursively remove adjacent duplicates string rremove(string &s) {

// Create an empty string to build the result
string sb = ""; 

// Get the size of the input string
int n = s.size(); 

// Iterate over the length of current string
for (int i = 0; i < n; i++) {
    bool repeated = false;

    // Check if the current characteris the same
    // as the next one
    while (i + 1 < n && s[i] == s[i + 1]) {
        repeated = true;  // Mark as repeated
      
        // Skip the next character
        // since it's a duplicate
        i++;  
    }

    // If the character was not repeated,
    // add it to the result string
    if (!repeated) sb += s[i];
}

// If no changes made, return the result string
if (n == sb.length())
    return sb;

// Otherwise, recursively call the function 
// to check for more duplicates
return rremove(sb);

}

int main() { string s = "geeksforgeek";
string result = rremove(s);
cout << result << endl;

return 0;

}

C

#include <stdio.h> #include <string.h>

// Function to recursively remove adjacent // duplicates void rremove(char *s){ // Get the size of the input string int n = strlen(s); // Initialize result string char sb[101] = ""; int k = 0;

// Iterate over the length of current string
for (int i = 0; i < n; i++){
    // Flag to check if the current character
    // is repeated
    int repeated = 0;

    // Check if the current character is the
    // same as the next one
    while (i + 1 < n && s[i] == s[i + 1]){
        // Mark as repeated
        repeated = 1;
        // Skip the next character since
        // it's a duplicate
        i++;
    }

    // If the character was not repeated,
    // add it to the result string
    if (!repeated)
        sb[k++] = s[i];
}

// If no changes made, return the result string
sb[k] = '\0';
if (n == k)
    strcpy(s, sb);
else{
    // Otherwise, recursively call function
    // to check for more duplicates
    strcpy(s, sb);
    rremove(s);
}

}

int main(){ char s[] = "geeksforgeek"; rremove(s); printf("%s", s);

return 0;

}

Java

class GfG { // Function to recursively remove adjacent duplicates static String rremove(String s) { // Create an empty string to build the result StringBuilder sb = new StringBuilder(); // Get the size of the input string int n = s.length();

    // Iterate over the length of current string
    for (int i = 0; i < n; i++) {
        // Flag to check if the current
        // character is repeated
        boolean repeated = false;

        // Check if the current character is the same as
        // the next one
        while (i + 1 < n
               && s.charAt(i) == s.charAt(i + 1)) {
            // Mark as repeated
            repeated = true;
            // Skip the next character since it's a
            // duplicate
            i++;
        }

        // If the character was not repeated,
        // add it to the result string
        if (!repeated)
            sb.append(s.charAt(i));
    }

    // If no changes were made, return the
    // result string
    if (n == sb.length())
        return sb.toString();

    // Otherwise, recursively call the function
    //  to check for more duplicates
    return rremove(sb.toString());
}

public static void main(String[] args){
    String s = "geeksforgeek";
    String result = rremove(s);
    System.out.println(result);
}

}

Python

Function to recursively remove adjacent duplicates

def rremove(s): # Initialize result string sb = "" # Get the size of the input string n = len(s)

# Iterate over the length of current string
i = 0
while i < n:
    # Flag to check if the current character
    # is repeated
    repeated = False

    # Check if the current character
    # is the same as the next one
    while i + 1 < n and s[i] == s[i + 1]:
        # Mark as repeated
        repeated = True
        # Skip the next character since
        # it's a duplicate
        i += 1

    # If the character was not repeated, 
    # add it to the result string
    if not repeated:
        sb += s[i]
    i += 1

# If no changes were made, return the result string
if n == len(sb):
    return sb

# Otherwise, recursively call the function
# to check for more duplicates
return rremove(sb)

def main(): s = "geeksforgeek" result = rremove(s) print(result)

if name == "main": main()

C#

using System;

class GfG { // Function to recursively remove adjacent duplicates static string rremove(string s) { // Initialize result string string sb = ""; // Get the size of the input string int n = s.Length;

    // Iterate over the length of current string
    for (int i = 0; i < n; i++) {
        // Flag to check if the current character is
        // repeated
        bool repeated = false;

        // Check if the current character is the same as
        // the next one
        while (i + 1 < n && s[i] == s[i + 1]) {
            // Mark as repeated
            repeated = true;
            // Skip the next character since it's a
            // duplicate
            i++;
        }

        // If the character was not repeated, add it to
        // the result string
        if (!repeated)
            sb += s[i];
    }

    // If no changes were made, return the result string
    if (n == sb.Length)
        return sb;

    // Otherwise, recursively call the function to check
    // for more duplicates
    return rremove(sb);
}

static void Main(){
    string s = "geeksforgeek";
    string result = rremove(s);
    Console.WriteLine(result);
}

}

JavaScript

// Function to recursively remove adjacent duplicates function rremove(s) { // Initialize result string let sb = ""; // Get the size of the input string let n = s.length;

// Iterate over the length of current string
for (let i = 0; i < n; i++) {
    // Flag to check if the current character is
    // repeated
    let repeated = false;

    // Check if the current character is the same as the
    // next one
    while (i + 1 < n && s[i] === s[i + 1]) {
        // Mark as repeated
        repeated = true;
        // Skip the next character since it's a
        // duplicate
        i++;
    }

    // If the character was not repeated, add it to the
    // result string
    if (!repeated)
        sb += s[i];
}

// If no changes were made, return the result string
if (n === sb.length)
    return sb;

// Otherwise, recursively call the function to check for
// more duplicates
return rremove(sb);

}

//Driver Code let s = "geeksforgeek"; let result = rremove(s); console.log(result);

`

**Time Complexity: O(n^2), In the worst case, the function may need to iterate almost through the entire string for each recursion, which makes the time complexity as O(N^2).
**Auxiliary Space: O(n^2), as we are storing the new string in each recursive call and there can be n recursive call in the worst case.

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

This solution also removes adjacent duplicates but it does this by modifying the string in place. It uses an index to track where to place non-duplicate characters. It skips over duplicate characters and moves only unique characters forward. After processing the original string, trims the original string to remove extra characters. If any adjacent duplicates were removed in this process then recursively call the function itself to repeat this process again. This approach is efficient because it modifies the string directly without creating new ones.

C++ `

#include using namespace std;

// Helper function to remove adjacent duplicates void remove_util(string &str, int n) {

 // Get the length of the string
int len = str.length(); 

 // Index to store the result string
int k = 0; 

// Iterate over the string to remove adjacent
// duplicates
for (int i = 0; i < n; i++) {

    // Check if the current character is the same
    //  as the next one
    if (i < n - 1 && str[i] == str[i + 1]) {
        
        // Skip all the adjacent duplicates
        while (i < n - 1 && str[i] == str[i + 1]) {
            i++;
        }
    } else {
        
        // If not a duplicate, store the character
        str[k++] = str[i];
    }
}

// Remove the remaining characters from the
// original string
str.erase(k);

// If any adjacent duplicates were removed,
//  recursively check for more
if (k != n)
    remove_util(str, k);

}

// Function to initiate the removal of adjacent // duplicates string rremove(string s) {

// Call the helper function
remove_util(s, s.length());

// Return the modified string
return s;  

}

int main() { string s = "geeksforgeek"; cout << rremove(s) << endl; return 0; }

C

#include <stdio.h> #include <string.h>

// Helper function to remove adjacent duplicates void remove_util(char* str, int n) { // Get the length of the string int len = strlen(str);

// Index to store the result string
int k = 0;

// Iterate over the string to remove adjacent
// duplicates
for (int i = 0; i < n; i++) {
    // Check if the current character
    // is the same as the next one
    if (i < n - 1 && str[i] == str[i + 1]) {
        // Skip all the adjacent duplicates
        while (i < n - 1 && str[i] == str[i + 1]) {
            i++;
        }
    } else {
        // If not a duplicate, store the character
        str[k++] = str[i];
    }
}

// Remove the remaining characters from the 
// original string
str[k] = '\0';

// If any adjacent duplicates were removed,
// recursively check for more
if (k != n)
    remove_util(str, k);

}

// Function to initiate the removal of adjacent // duplicates void rremove(char* s) { // Call the helper function remove_util(s, strlen(s)); }

int main() { char s[] = "geeksforgeek"; rremove(s); printf("%s\n", s); return 0; }

Java

public class GfG { // Helper function to remove adjacent duplicates static void removeUtil(StringBuilder str, int n){ // Index to store the result string int k = 0;

    // Iterate over the string to remove adjacent
    // duplicates
    for (int i = 0; i < n; i++) {
        // Check if the current character is the same as
        // the next one
        if (i < n - 1
            && str.charAt(i) == str.charAt(i + 1)) {
            // Skip all the adjacent duplicates
            while (i < n - 1
                   && str.charAt(i)
                          == str.charAt(i + 1)) {
                i++;
            }
        }
        else {
            // If not a duplicate, store the character
            str.setCharAt(k++, str.charAt(i));
        }
    }

    // Remove the remaining characters from the original
    // string
    str.setLength(k);

    // If any adjacent duplicates were removed,
    // recursively check for more
    if (k != n)
        removeUtil(str, k);
}

// Function to initiate the removal of adjacent
// duplicates
static String rremove(String s){
    StringBuilder str = new StringBuilder(s);

    // Call the helper function
    removeUtil(str, str.length());

    // Return the modified string
    return str.toString();
}

public static void main(String[] args){
    String s = "geeksforgeek";
    System.out.println(rremove(s));
}

}

Python

Helper function to remove adjacent duplicates

def remove_util(s, n):

# Index to store the result string
k = 0

# Iterate over the string to remove adjacent duplicates
i = 0
while i < n:
  
    # Check if the current character is the same as the next one
    if i < n - 1 and s[i] == s[i + 1]:
      
        # Skip all the adjacent duplicates
        while i < n - 1 and s[i] == s[i + 1]:
            i += 1
    else:
        # If not a duplicate, store the character
        s[k] = s[i]
        k += 1
    i += 1

# Remove the remaining characters from the original string
s = s[:k]

# If any adjacent duplicates were removed, recursively check for more
if k != n:
    s = remove_util(list(s), k)

return s

Function to initiate the removal of adjacent duplicates

def rremove(s): # Convert the string to a list to allow modification s = list(s)

# Call the helper function
return ''.join(remove_util(s, len(s)))

def main(): s = "geeksforgeek" print(rremove(s))

if name == "main": main()

C#

using System; using System.Text;

class GfG { // Helper function to remove adjacent duplicates static void RemoveUtil(StringBuilder str, int n) { // Index to store the result string int k = 0;

    // Iterate over the string to remove adjacent
    // duplicates
    for (int i = 0; i < n; i++) {
        // Check if the current character 
        // is the same as the next one
        if (i < n - 1 && str[i] == str[i + 1]) {
            // Skip all the adjacent duplicates
            while (i < n - 1 
                   && str[i] == str[i + 1]) {
                i++;
            }
        }
        else {
            // If not a duplicate, store the character
            str[k++] = str[i];
        }
    }

    // Remove the remaining characters from 
    // the original string
    str.Length = k;

    // If any adjacent duplicates were removed,
    // recursively check for more
    if (k != n)
        RemoveUtil(str, k);
}

// Function to initiate the removal of adjacent
// duplicates
static string RRemove(string s)
{
    StringBuilder str = new StringBuilder(s);

    // Call the helper function
    RemoveUtil(str, str.Length);

    // Return the modified string
    return str.ToString();
}

static void Main()
{
    string s = "geeksforgeek";
    Console.WriteLine(RRemove(s));
}

}

JavaScript

// Helper function to remove adjacent duplicates function removeUtil(str, n) { let k = 0; let result = [];

// Iterate over the string to remove adjacent
// duplicates
for (let i = 0; i < n; i++) {

    // Check if the current character is the
    // same as the next one
    if (i < n - 1 && str[i] === str[i + 1]) {
    
        // Skip all the adjacent duplicates
        while (i < n - 1 && str[i] === str[i + 1]) {
            i++;
        }
    } else {
    
        // If not a duplicate, store the character
        result[k++] = str[i];
    }
}

// If any adjacent duplicates were removed,
// recursively check for more
if (k !== n) {
    return removeUtil(result.join(''), k);
}

return result.join('');

}

// Function to initiate the removal of adjacent // duplicates function rremove(s) { // Call the helper function return removeUtil(s, s.length); }

//Driver Code let s = "geeksforgeek"; console.log(rremove(s));

`

**Time Complexity: O(n^2), In the worst case, the function may need to iterate almost through the entire string for each recursion, which makes the time complexity as O(n^2).
**Auxiliary Space: O(n), considering the recursive call stack.