How can I delete consecutive duplicates recursively without an int parameter?

I need to fix my previous code. If the input is "aabbcdefgghijkllaa", the output needs to be "abcdefghijkla". My current code that I have changed outputs "alkjihgfedcba". (The input may not necessarily be in alphabetical order, and the output should be in the same order as the original input.) Should I just create a new method to reverse that or is there a way to fix it with my current methods?

Here is my code:

package recursion;

public class recursion {

    static String a = "aabbcdefgghijkllaa";
    static int b=a.length()-1;
    static String result = "";

    public static void main(String[] args){

        System.out.println("Input: " + a);
        System.out.print("Output: ");
        removeDuplicates(a);
    }

    public static String removeDuplicates(String a){

        if (b <= 0){
            System.out.print(a.charAt(0));
            result=result+a.charAt(0);
        }
        else if (a.charAt(b) == a.charAt(b-1)) {
            b--;
            removeDuplicates(a);              
        }
        else {
            System.out.print(a.charAt(b));
            result=result+a.charAt(b);
            b--;
            removeDuplicates(a);
        }
        return a;
    }
}

Changing b to 0 (and the - to +) gives an output of just "a", which is also not what I need. How can I fix this?

Answer:1

It may be better to break this up into specific goals instead:

  • What you want to do when the string is null or empty
  • What you want to do with a string of size < 2
  • What you want to do with a string of size >= 2

...and what the conditions are for each scenario.

Note that the code that follows is mostly untested; it's meant to give you a rough idea but not a complete solution. It works for your examples, but it definitely has some shortcomings to it.


Let's think what happens when we get an example string "aabccdde". We want to keep track of the first letter in that string as well as the rest of the string. It wouldn't hurt to have something to append to either.

With that, we come up with this signature for a recursive method:

private static String deleteConsecutiveDuplicates(String string,
                                                  char lastSeenLetter,
                                                  StringBuilder builder)

This isn't something you expose to just anyone, so you cover it up with another method which does the initial, "Are you empty/null?" checks.

static String deleteConsecutiveDuplicates(String string) {

    if(null == string || string.length() == 0) {
        return string;
    } else {
        return deleteConsecutiveDuplicates(string.substring(1),
                                           string.charAt(0),
                                           new StringBuilder());
    }
}

Let's now talk about what we do when we see the string.

Round 1: 'a' | "abccdde" | ""

The character that we last saw is the same as the first character in the string.

  • Add it to the builder
  • Advance to the substring denoted by index [2, n), and take the "last seen letter" as the character at position 1 of the passed in string.

Round 2: 'b' | "ccdde" | "a"

The two characters are completely different.

  • Append b
  • Advance to the substring denoted by index [1, n) and take the "last seen letter" as the character at position 0 of the passed in string.

Repeat these steps until you are left with the string "abcde".


The ideology here is to break up the problem into smaller sub-problems that are easier to digest and tackle. In general, you're only ever adding one character at a time through the last seen letter variable.

There are other edge cases that this simple approach doesn't exactly account for (one letter, multiple repeated instances of it; i.e. "zzzzzzz" will leave off one "z"), but the hope is that this will give you somewhere to start.

private static String deleteConsecutiveDuplicates(String string, char lastSeenLetter, StringBuilder builder) {
    if(string.length() == 0) {
        builder.append(lastSeenLetter);
    } else if(string.charAt(0) == lastSeenLetter) {
        builder.append(lastSeenLetter);
        if(string.length() < 2 ) {
            return builder.toString();
        }
        return deleteConsecutiveDuplicates(string.substring(2), string.charAt(1), builder);
    } else {
        if(builder.charAt(builder.length() - 1) != lastSeenLetter) {
            builder.append(lastSeenLetter);
        }
        return deleteConsecutiveDuplicates(string.substring(1), string.charAt(0), builder);
    }
    return builder.toString();
}
Answer:2

If you want a recursive solution without any string position variables, you can try this (though it's pretty ineffective):

public class recursion {

    static String a = "aabbcdefgghijkllaa";

    public static void main(String[] args){

        System.out.println("Input: " + a);
        System.out.println("Output: " + removeDuplicates(a));
    }

    public static String removeDuplicates(String a){
        if(a.length() < 2)
            return a;
        return a.charAt(0)+removeDuplicates(a.substring(a.charAt(0) == a.charAt(1) ? 2 : 1));
    }
}

Here removeDuplicates method doesn't print anything, it just forms the resulting string calling itself for the substring skipping the second character if it's the same as the first.

Answer:3

I've a DB query using ORDERED BY and the corresponding result set is processed to a list of custom objects. The object class does not implement Comparable . It however overrides equals() and ...

I have created a JButton class that recieving Action, the JButton class includes keystrokes & mouse listener so i can use the same class in multiple frames as needed. My problems is that: JButton ...

I wish to pass to Hibernate's SessionFactory hibernate.hbm2ddl.auto=update and see in log file generated sql statements. Is it possible w/o java coding (know how to achieve the result with ...

This post shows that the code below creates a List from an array. double[] features = new double[19]; List<Double> list = new ArrayList(Arrays.asList(features)); I'm expecting list to contain ...