0

I have a piece of code and I'm a bit confused how to deal with my issue so, please review method below. I was trying to search for a solution but unfortunately none of them fit my needs so I am looking for an advice here. The method is taking a String and removing duplicated characters so for example - input: ABBCDEF should return ABCDEF, but when entering i+1 in the last iteration I got IndexOutOfBound Exception, so I can iterate until string.length-1 but then I loose the last element, what is the SMARTEST solution in your opinion, thanks.

public String removeDuplicates(String source){
        if(source.length() < 2){
            return source;
        }

        StringBuilder noDuplicates = new StringBuilder();
        char[] string = source.toCharArray();

        for(int i = 0; i < string.length-1; i++){
            if(string[i] != string[i+1]){
                noDuplicates.append(string[i]);
            }
        }
        return noDuplicates.toString();
    }

5 Answers5

0

You could simply append the last character after the loop:

public String removeDuplicates(String source){

    ...

    noDuplicates.append(string[string.length - 1]);
    return noDuplicates.toString();
}
Henry Twist
  • 5,666
  • 3
  • 19
  • 44
  • Yea but I need another if condition to check if last two letters are not duplicated, because in solution which you suggest we are not checking that. So I cannot just simply append. – just_curious Jul 02 '21 at 07:25
  • Can you give me an example when it wouldn't work? Your loop already checks the last two and if they are duplicates, it doesn't ever append. – Henry Twist Jul 02 '21 at 09:53
0

You could do this like so: append the first character in source, and then only append subsequent characters if they are not equal to the previously-appended character.

if (source.isEmpty()) {
  return source; // Or "", it doesn't really matter.
}
StringBuilder sb = new StringBuilder();
sb.append(source.charAt(0));
for (int i = 1; i < source.length(); ++i) {
  char c = source.charAt(i);
  if (c != sb.charAt(sb.length() - 1)) {
    sb.append(c);
  }
}
return sb.toString();

But if you wanted to do this more concisely, you could do it with regex:

return source.replaceAll("(.)\\1+", "$1");
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • Hi mate. I'm trying to make sure I understand how the regex solution works... `(.)` selects any character into a group, `\\1+` grabs one or more of the character in this group (which are directly adjacent to each other, it won't catch repeating characters not directly next to each other) and then `$1` finds the end of the String it's adjusting and appends the character put in the group (not sure on this interpretation of what it's replacing)? – Tim Hunter Jul 02 '21 at 14:07
  • 1
    "and then $1 finds the end of the String" no, it's just referring to the capture group, that is, the first character is a sequence of repeating characters. – Andy Turner Jul 02 '21 at 16:55
0

You have a simple logic error: You make your string to a char array. That is fine, but the length property of any array will show you the human way of counting if someting is in it.

If there is 1 element the length will be 1
2 -> 2
3 -> 3
etc.
You get the idea.

So when you go string[i + 1] you go one character to far. You could just change the abort condition to

i < = string.length - 2

Or you could write a string iterator, to be able to access the next element, but that seems like overkill for this example

firesnake
  • 11
  • 1
  • 2
0

If you wish to remove all repeating characters regardless of their position in the given String you might want to consider using the chars() method which provides a IntStream of the chars and that has the distinct() method to filter out repeating values. You can then put them back together with a StringBuilder like so:

public class RemoveDuplicatesTest {
  public static void main(String[] args) {
    String value = "ABBCDEFE";
    System.out.println("No Duplicates: " + removeDuplicates(value));
  }
  
  public static String removeDuplicates(String value) {
    StringBuilder result = new StringBuilder();
    value.chars().distinct().forEach(c -> result.append((char) c));
    return result.toString();
  }
}
Tim Hunter
  • 826
  • 5
  • 10
0

This is just what LinkedHashSet was made for! Under the hood it's a HashSet with an iterator to keep track of insertion order, so you can remove duplicates by adding to the set, then reconstruct the string with guaranteed ordering.

public static String removeDuplicates(String source) {
    Set<String> dupeSet = new LinkedHashSet<>();

    for (Character v : source.toCharArray()) {
        dupeSet.add(v.toString());
    }

    return String.join("", dupeSet);
}
jeff_hinton
  • 383
  • 1
  • 2
  • 8