Recursively remove all adjacent duplicates

23 Jun, 2022
Given a string, recursively remove adjacent duplicate characters from the string. The output string should not have any adjacent duplicates. See the following examples.
Examples: 
Input: azxxzy Output: ay 
First “azxxzy” is reduced to “azzy”. 
The string “azzy” contains duplicates, 
so it is further reduced to “ay”.
Input: geeksforgeeg Output: gksfor 
First “geeksforgeeg” is reduced to “gksforgg”. 
The string “gksforgg” contains duplicates, 
so it is further reduced to “gksfor”.
Input: caaabbbaacdddd Output: Empty String
Input: acaaabbbacdddd Output: acac 
The following approach can be followed to remove duplicates in O(N) time: 
Start from the leftmost character and remove duplicates at left corner if there are any.
The first character must be different from its adjacent now. Recur for string of length n-1 (string without first character).
Let the string obtained after reducing right substring of length n-1 be rem_str. There are three possible cases If first character of rem_str matches with the first character of original string, remove the first character from rem_str.If remaining string becomes empty and last removed character is same as first character of original string. Return empty string.Else, append the first character of the original string at the beginning of rem_str.
If first character of rem_str matches with the first character of original string, remove the first character from rem_str.If remaining string becomes empty and last removed character is same as first character of original string. Return empty string.Else, append the first character of the original string at the beginning of rem_str.
If first character of rem_str matches with the first character of original string, remove the first character from rem_str.
If remaining string becomes empty and last removed character is same as first character of original string. Return empty string.
Else, append the first character of the original string at the beginning of rem_str.
Return rem_str.
Below image is a dry run of the above approach:
Below is the implementation of the above approach:
C++14
C
Java
Python
C#
Javascript
// C++ program to remove all adjacent duplicates from a string#include <bits/stdc++.h>using namespace std; // Recursively removes adjacent duplicates from str and// returns new string. last_removed is a pointer to// last_removed characterchar* removeUtil(char* str, char* last_removed){     // If length of string is 1 or 0    if (str[0] == '\0' || str[1] == '\0')        return str;     // Remove leftmost same characters and recur for    // remaining string    if (str[0] == str[1]) {        *last_removed = str[0];        while (str[1] && str[0] == str[1])            str++;        str++;        return removeUtil(str, last_removed);    }     // At this point, the first character is definitely    // different from its adjacent. Ignore first character    // and recursively remove characters from remaining    // string    char* rem_str = removeUtil(str + 1, last_removed);     // Check if the first character of the rem_string    // matches with the first character of the original    // string    if (rem_str[0] && rem_str[0] == str[0]) {        *last_removed = str[0];         // Remove first character        return (rem_str + 1);    }     // If remaining string becomes empty and last removed    // character is same as first character of original    // string. This is needed for a string like "acbbcddc"    if (rem_str[0] == '\0' && *last_removed == str[0])        return rem_str;     // If the two first characters of str and rem_str don't    // match, append first character of str before the first    // character of rem_str.    rem_str--;    rem_str[0] = str[0];    return rem_str;} // Function to removechar* remove(char* str){    char last_removed = '\0';    return removeUtil(str, &last_removed);} // Driver program to test above functionsint main(){    char str1[] = "geeksforgeeg";    cout << remove(str1) << endl;     char str2[] = "azxxxzy";    cout << remove(str2) << endl;     char str3[] = "caaabbbaac";    cout << remove(str3) << endl;     char str4[] = "gghhg";    cout << remove(str4) << endl;     char str5[] = "aaaacddddcappp";    cout << remove(str5) << endl;     char str6[] = "aaaaaaaaaa";    cout << remove(str6) << endl;     char str7[] = "qpaaaaadaaaaadprq";    cout << remove(str7) << endl;     char str8[] = "acaaabbbacdddd";    cout << remove(str8) << endl;     char str9[] = "acbbcddc";    cout << remove(str9) << endl;     return 0;} // This code is contributed by Aditya Kumar (adityakumar129)
// C program to remove all adjacent duplicates from a string#include <stdio.h>#include <string.h> // Recursively removes adjacent duplicates from str and// returns new string. last_removed is a pointer to// last_removed characterchar* removeUtil(char* str, char* last_removed){     // If length of string is 1 or 0    if (str[0] == '\0' || str[1] == '\0')        return str;     // Remove leftmost same characters and recur for    // remaining string    if (str[0] == str[1]) {        *last_removed = str[0];        while (str[1] && str[0] == str[1])            str++;        str++;        return removeUtil(str, last_removed);    }     // At this point, the first character is definitely    // different from its adjacent. Ignore first character    // and recursively remove characters from remaining    // string    char* rem_str = removeUtil(str + 1, last_removed);     // Check if the first character of the rem_string    // matches with the first character of the original    // string    if (rem_str[0] && rem_str[0] == str[0]) {        *last_removed = str[0];         // Remove first character        return (rem_str + 1);    }     // If remaining string becomes empty and last removed    // character is same as first character of original    // string. This is needed for a string like "acbbcddc"    if (rem_str[0] == '\0' && *last_removed == str[0])        return rem_str;     // If the two first characters of str and rem_str don't    // match, append first character of str before the first    // character of rem_str.    rem_str--;    rem_str[0] = str[0];    return rem_str;} // Function to removechar* removes(char* str){    char last_removed = '\0';    return removeUtil(str, &last_removed);} // Driver program to test above functionsint main(){    char str1[] = "geeksforgeeg";    printf("%s\n", removes(str1));     char str2[] = "azxxxzy";    printf("%s\n", removes(str2));     char str3[] = "caaabbbaac";    printf("%s\n", removes(str3));     char str4[] = "gghhg";    printf("%s\n", removes(str4));     char str5[] = "aaaacddddcappp";    printf("%s\n", removes(str5));     char str6[] = "aaaaaaaaaa";    printf("%s\n", removes(str6));     char str7[] = "qpaaaaadaaaaadprq";    printf("%s\n", removes(str7));     char str8[] = "acaaabbbacdddd";    printf("%s\n", removes(str8));     char str9[] = "acbbcddc";    printf("%s\n", removes(str9));     return 0;} // This code is contributed by Aditya Kumar (adityakumar129)
// Java program to remove all adjacent duplicates from a// stringimport java.io.*;import java.util.*; class GFG {     static char last_removed; //will store the last char removed during recursion       // Recursively removes adjacent duplicates from str and    // returns new string. last_removed is a pointer to    // last_removed character    static String removeUtil(String str)    {         // If length of string is 1 or 0        if (str.length() == 0 || str.length() == 1)            return str;         // Remove leftmost same characters and recur for        // remaining string        if (str.charAt(0) == str.charAt(1)) {            last_removed = str.charAt(0);            while (str.length() > 1                   && str.charAt(0) == str.charAt(1))                str = str.substring(1, str.length());            str = str.substring(1, str.length());            return removeUtil(str);        }         // At this point, the first character is definitely        // different from its adjacent. Ignore first        // character and recursively remove characters from        // remaining string        String rem_str            = removeUtil(str.substring(1, str.length()));         // Check if the first character of the rem_string        // matches with the first character of the original        // string        if (rem_str.length() != 0            && rem_str.charAt(0) == str.charAt(0)) {            last_removed = str.charAt(0);             // Remove first character            return rem_str.substring(1, rem_str.length());        }         // If remaining string becomes empty and last        // removed character is same as first character of        // original string. This is needed for a string like        // "acbbcddc"        if (rem_str.length() == 0            && last_removed == str.charAt(0))            return rem_str;         // If the two first characters of str and rem_str        // don't match, append first character of str before        // the first character of rem_str        return (str.charAt(0) + rem_str);    }     static String remove(String str)    {        last_removed = '\0';        return removeUtil(str);    }     // Driver code    public static void main(String args[])    {        String str1 = "geeksforgeeg";        System.out.println(remove(str1));         String str2 = "azxxxzy";        System.out.println(remove(str2));         String str3 = "caaabbbaac";        System.out.println(remove(str3));         String str4 = "gghhg";        System.out.println(remove(str4));         String str5 = "aaaacddddcappp";        System.out.println(remove(str5));         String str6 = "aaaaaaaaaa";        System.out.println(remove(str6));         String str7 = "qpaaaaadaaaaadprq";        System.out.println(remove(str7));         String str8 = "acaaabbbacdddd";        System.out.println(remove(str8));    }} // This code is contributed by Aditya Kumar (adityakumar129)
# Python program to remove# all adjacent duplicates from a string # Recursively removes adjacent# duplicates from str and returns# new string. last_removed is a# pointer to last_removed characterdef removeUtil(string, last_removed):     # If length of string is 1 or 0    if len(string) == 0 or len(string) == 1:        return string     # Remove leftmost same characters    # and recur for remaining    # string    if string[0] == string[1]:        last_removed = ord(string[0])        while len(string) > 1 and string[0] ==                                    string[1]:            string = string[1:]        string = string[1:]         return removeUtil(string, last_removed)     # At this point, the first    # character is definitely different    # from its adjacent. Ignore first    # character and recursively    # remove characters from remaining string    rem_str = removeUtil(string[1:], last_removed)     # Check if the first character    # of the rem_string matches    # with the first character of    # the original string    if len(rem_str) != 0 and rem_str[0] ==                                         string[0]:        last_removed = ord(string[0])        return (rem_str[1:])     # If remaining string becomes    # empty and last removed character    # is same as first character of    # original string. This is needed    # for a string like "acbbcddc"    if len(rem_str) == 0 and last_removed ==                                   ord(string[0]):        return rem_str     # If the two first characters of    # str and rem_str don't match,    # append first character of str    # before the first character of    # rem_str.    return ([string[0]] + rem_str) def remove(string):    last_removed = 0    return toString(removeUtil(toList(string),                                    last_removed)) # Utility functionsdef toList(string):    x = []    for i in string:        x.append(i)    return x def toString(x):    return ''.join(x) # Driver programstring1 = "geeksforgeeg"print remove(string1) string2 = "azxxxzy"print remove(string2) string3 = "caaabbbaac"print remove(string3) string4 = "gghhg"print remove(string4) string5 = "aaaacddddcappp"print remove(string5) string6 = "aaaaaaaaaa"print remove(string6) string7 = "qpaaaaadaaaaadprq"print remove(string7) string8 = "acaaabbbacdddd"print remove(string8) string9 = "acbbcddc"print remove(string9) # This code is contributed by BHAVYA JAIN
// C# program to remove// all adjacent duplicates// from a stringusing System; class GFG{   // Recursively removes adjacent  //  duplicates from str and returns  // new string. last_removed is a  // pointer to last_removed character  static string removeUtil(string str,                           char last_removed)  {     // If length of string is 1 or 0    if (str.Length == 0 || str.Length == 1)      return str;     // Remove leftmost same characters    // and recur for remaining     // string    if (str[0] == str[1])    {      last_removed = str[0];      while (str.Length > 1 && str[0] ==             str[1]) {        str = str.Substring(1, str.Length - 1);      }      str = str.Substring(1, str.Length - 1);      return removeUtil(str, last_removed);    }     // At this point, the first    // character is definitely different     // from its adjacent. Ignore first    // character and recursively     // remove characters from remaining string    string rem_str = removeUtil(str.Substring(      1,str.Length - 1), last_removed);     // Check if the first character of    // the rem_string matches with     // the first character of the original string    if (rem_str.Length != 0 &&        rem_str[0] == str[0])    {      last_removed = str[0];       // Remove first character      return rem_str.Substring(1,rem_str.Length - 1);    }     // If remaining string becomes    // empty and last removed character    // is same as first character of    // original string. This is needed    // for a string like "acbbcddc"    if (rem_str.Length == 0 && last_removed ==        str[0])      return rem_str;     // If the two first characters    // of str and rem_str don't match,     // append first character of str    // before the first character of    // rem_str    return (str[0] + rem_str);  }   static string remove(string str)   {    char last_removed = '\0';    return removeUtil(str, last_removed);        }   // Driver code  public static void Main()  {     string str1 = "geeksforgeeg";    Console.Write(remove(str1) + "\n");     string str2 = "azxxxzy";    Console.Write(remove(str2)  + "\n");     string str3 = "caaabbbaac";    Console.Write(remove(str3)  + "\n");     string str4 = "gghhg";    Console.Write(remove(str4)  + "\n");     string str5 = "aaaacddddcappp";    Console.Write(remove(str5)  + "\n");     string str6 = "aaaaaaaaaa";    Console.Write(remove(str6)  + "\n");     string str7 = "qpaaaaadaaaaadprq";    Console.Write(remove(str7)  + "\n");     string str8 = "acaaabbbacdddd";    Console.Write(remove(str8)  + "\n");     string str9 = "acbbcdd";    Console.Write(remove(str9)  + "\n");   }} // This code is contributed by Samim Hossain Mondal.
<script> // Python program to remove// all adjacent duplicates from a string // Recursively removes adjacent// duplicates from str and returns// new string. last_removed is a// pointer to last_removed characterfunction removeUtil(string, last_removed){     // If length of string is 1 or 0    if(string.length == 0 || string.length == 1)        return string     // Remove leftmost same characters    // and recur for remaining    // string    if(string[0] == string[1]){        last_removed = string.charCodeAt(0)        while(string.length > 1 && string[0] == string[1])            string = string.substr(1,)        string = string.substr(1,)         return removeUtil(string, last_removed)    }     // At this point, the first    // character is functioninitely different    // from its adjacent. Ignore first    // character and recursively    // remove characters from remaining string    let rem_str = removeUtil(string.substr(1,), last_removed)     // Check if the first character    // of the rem_string matches    // with the first character of    // the original string    if(rem_str.length != 0 && rem_str[0] == string[0]){        last_removed = string.charCodeAt(0)        return rem_str.substr(1,)    }     // If remaining string becomes    // empty and last removed character    // is same as first character of    // original string. This is needed    // for a string like "acbbcddc"    if(rem_str.length == 0 && last_removed == string.charCodeAt(0))        return rem_str     // If the two first characters of    // str and rem_str don't match,    // push first character of str    // before the first character of    // rem_str.     let res = string[0] + rem_str     return res} function remove(string){    let last_removed = 0    return removeUtil(string,last_removed)}  // Driver programlet string1 = "geeksforgeeg"document.write(remove(string1),"</br>") let string2 = "azxxxzy"document.write(remove(string2),"</br>") let string3 = "caaabbbaac"document.write(remove(string3),"</br>") let string4 = "gghhg"document.write(remove(string4),"</br>") let string5 = "aaaacddddcappp"document.write(remove(string5),"</br>") let string6 = "aaaaaaaaaa"document.write(remove(string6),"</br>") let string7 = "qpaaaaadaaaaadprq"document.write(remove(string7),"</br>") let string8 = "acaaabbbacdddd"document.write(remove(string8),"</br>") let string9 = "acbbcddc"document.write(remove(string9),"</br>") // This code is contributed by shinjanpatra </script>
gksfor
ay

g
a

qrq
acac
a

Time Complexity: The time complexity of the solution can be written as T(n) = T(n-k) + O(k) where n is length of the input string and k is the number of first characters which are same. Solution of the recurrence is O(n)
Thanks to Prachi Bodke for suggesting this problem and initial solution. 
Another Approach:The idea here is to check whether the String remStr has the repeated character that matches the last char of the parent String. If that is happening then we have to keep removing that character before concatenating string s and string remStr.
Below is the implementation of the above approach:
C++
Java
Python3
Javascript
// C++ Program for above approach #include <bits/stdc++.h>using namespace std; // Recursively removes adjacent// duplicates from str and// returns new string. las_removed// is a pointer to// last_removed characterstring removeDuplicates(string s, char ch){     // If length of string is 1 or 0    if (s.length() <= 1) {        return s;    }     int i = 0;    while (i < s.length()) {        if (i + 1 < s.length() && s[i] == s[i + 1]) {            int j = i;            while (j + 1 < s.length() && s[j] == s[j + 1]) {                j++;            }            char lastChar = i > 0 ? s[i - 1] : ch;             string remStr = removeDuplicates(                s.substr(j + 1, s.length()), lastChar);             s = s.substr(0, i);            int k = s.length(), l = 0;             // Recursively remove all the adjacent            // characters formed by removing the            // adjacent characters            while (remStr.length() > 0 && s.length() > 0                   && remStr[0] == s[s.length() - 1]) {                 // Have to check whether this is the                // repeated character that matches the                // last char of the parent String                while (remStr.length() > 0                       && remStr[0] != ch                       && remStr[0] == s[s.length() - 1]) {                    remStr                        = remStr.substr(1, remStr.length());                }                s = s.substr(0, s.length() - 1);            }            s = s + remStr;            i = j;        }        else {            i++;        }    }    return s;} // Driver Codeint main(){     string str1 = "mississipie";    cout << removeDuplicates(str1, ' ') << endl;     string str2 = "ocvvcolop";    cout << removeDuplicates(str2, ' ') << endl;} // This code is contributed by nirajgusain5
// Java Program for above approachimport java.util.*;import java.lang.*;import java.io.*; class GFG{   // Recursively removes adjacent  // duplicates from str and  // returns new string. las_removed  // is a pointer to  // last_removed character  private static String removeDuplicates(    String s, char ch)  {     // If length of string is 1 or 0    if (s == null || s.length() <= 1)    {      return s;    }     int i = 0;    while (i < s.length())    {      if (i + 1 < s.length()          && s.charAt(i) == s.charAt(i + 1))      {        int j = i;        while (j + 1 < s.length()               && s.charAt(j) ==               s.charAt(j + 1))        {          j++;        }        char lastChar          = i > 0 ? s.charAt(i - 1) : ch;         String remStr = removeDuplicates(          s.substring(j + 1, s.length()),          lastChar);         s = s.substring(0, i);        int k = s.length(), l = 0;         // Recursively remove all the adjacent        // characters formed by removing the        // adjacent characters        while (remStr.length() > 0 &&               s.length() > 0 &&               remStr.charAt(0) ==               s.charAt(s.length() - 1))        {           // Have to check whether this is the          // repeated character that matches the          // last char of the parent String          while (remStr.length() > 0                 && remStr.charAt(0) != ch                 && remStr.charAt(0)                 == s.charAt(s.length()                             - 1))          {            remStr = remStr.substring(              1, remStr.length());          }          s = s.substring(0, s.length() - 1);        }        s = s + remStr;        i = j;      }      else      {        i++;      }    }    return s;  }   // Driver Code  public static void main(String[] args)  {     String str1 = "mississipie";    System.out.println(removeDuplicates(      str1, ' '));    String str2 = "ocvvcolop";    System.out.println(removeDuplicates(      str2, ' '));  }} // This code is contributed by Niharika Sahai
# Python Program for above approach # Recursively removes adjacent# duplicates from str and# returns new string. las_removed# is a pointer to# last_removed characterdef removeDuplicates(s,ch):     # If length of string is 1 or 0    if (len(s) <= 1):        return s     i = 0    while (i < len(s)):        if (i + 1 < len(s) and s[i] == s[i + 1]):            j = i            while (j + 1 < len(s) and s[j] == s[j + 1]):                j += 1                         lastChar = s[i - 1] if(i > 0) else ch             remStr = removeDuplicates(s[j + 1: len(s)], lastChar)             s = s[0: i]            k,l = len(s), 0             # Recursively remove all the adjacent            # characters formed by removing the            # adjacent characters            while (len(remStr) > 0 and len(s) > 0                and remStr[0] == s[len(s) - 1]):                 # Have to check whether this is the                # repeated character that matches the                # last char of the parent String                while (len(remStr) > 0                    and remStr[0] != ch                    and remStr[0] == s[len(s) - 1]):                    remStr = remStr[1: len(remStr)+1]                             s = s[0: len(s) - 1]                     s = s + remStr            i = j             else:            i += 1         return s # Driver Codestr1 = "mississipie"print(removeDuplicates(str1, ' ')) str2 = "ocvvcolop"print(removeDuplicates(str2, ' ')) # This code is contributed by shinjanpatra
<script> // JavaScript Program for above approach // Recursively removes adjacent// duplicates from str and// returns new string. las_removed// is a pointer to// last_removed characterfunction removeDuplicates(s,ch){     // If length of string is 1 or 0    if (s.length <= 1) {        return s;    }     let i = 0;    while (i < s.length) {        if (i + 1 < s.length && s[i] == s[i + 1]) {            let j = i;            while (j + 1 < s.length && s[j] == s[j + 1]) {                j++;            }            let lastChar = i > 0 ? s[i - 1] : ch;             let remStr = removeDuplicates(                s.substring(j + 1, s.length), lastChar);             s = s.substring(0, i);            let k = s.length, l = 0;             // Recursively remove all the adjacent            // characters formed by removing the            // adjacent characters            while (remStr.length > 0 && s.length > 0                && remStr[0] == s[s.length - 1]) {                 // Have to check whether this is the                // repeated character that matches the                // last char of the parent String                while (remStr.length > 0                    && remStr[0] != ch                    && remStr[0] == s[s.length - 1]) {                    remStr                        = remStr.substring(1, remStr.length+1);                }                s = s.substring(0, s.length - 1);            }            s = s + remStr;            i = j;        }        else {            i++;        }    }    return s;} // Driver Code let str1 = "mississipie";console.log(removeDuplicates(str1, ' ')); let str2 = "ocvvcolop";document.write(removeDuplicates(str2, ' '),"</br>"); // This code is contributed by shinjanpatra</script>
mpie
lop

Time Complexity: O(n) 
pragya29
rachana soma
Niharika Sahai
adityamutharia
nirajgusain5
surinderdawra388
surindertarika1234
samim2000
simmytarika5
shinjanpatra
adityakumar129
aryandhakad1
hardikkoriintern
Paytm
Samsung
Arrays
Recursion
Strings
Paytm
Samsung
Arrays
Strings
Recursion
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Multidimensional Arrays in Java
Linear Search
Introduction to Arrays
Given an array A[] and a number x, check for pair in A[] with sum as x (aka Two Sum)
K'th Smallest/Largest Element in Unsorted Array | Set 1
Write a program to print all permutations of a given string
Given an array A[] and a number x, check for pair in A[] with sum as x (aka Two Sum)
Recursion
Program for Tower of Hanoi
Backtracking | Introduction