Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I count the number of unique characters in a string? - Updated

For example, the string "abc" should give 3 unique characters, while the string "abcccd" would give 4 unique characters. I'm not allowed to use Map, HashMap, TreeMap, Set, HashSet, StringBuffer or TreeSet in this.

So far I'm trying to use a for loop but when I run the program I keep getting 0 unique characters. I'm kind of new at Java so I really have no idea what I'm doing.

Edit: so I changed the code around and I'm getting a result but it ends up being 1 less than what I want. I'll type in 'abc' and the result will come up as "2 unique characters" instead of three. To counter that I put (uniqueChars + 1) in the println statement. Is this a good correction? If the user puts nothing, it will still say that there's 1 unique character.

Updated code:

    userText = userText.toLowerCase(); // userText is declared earlier in the program 
                                       // as the user's input. Setting this to lowercase 
                                       // so it doesn't say "a" and "A" are two different 
                                       // characters.
    int uniqueChars = 0;
    for (int i = 0; i < lengthText-1; i++) { // lengthText is declared earlier 
                                              // as userText.length();
        if (userText.charAt(i) != userText.charAt(i+1))
            uniqueChars++;
    }
    System.out.println("there are " + (uniqueChars + 1) + " unique characters in your string.");
}
like image 538
newJavaUser Avatar asked Mar 25 '14 21:03

newJavaUser


1 Answers

How about this one? It's a regex solution rather than a loop:

public static int countUniqueCharacters(String input)
{
    String unique = input.replaceAll("(.)(?=.*?\\1)", "");
    return unique.length();
}

If the program needs to be case-insensitive, you can use this instead:

public static int countUniqueCharacters(String input)
{
    String unique = input.replaceAll("(?i)(.)(?=.*?\\1)", "");
    return unique.length();
}

You could make this a single-line method with return input.replaceAll(...).length();

Regex Explained:

  • . matches any character
  • (...) creates a capturing group, to be referenced later
  • (?=...) creates a lookahead, to look forwards in the input
  • .*? matches anything between the character and its match (non-greedy matching)
  • \\1 matches the first capturing group
  • (?i) sets the case-insensitive flag

So, the regex will look for any character which has a duplicate later in the string, and then replaceAll will replace it with the empty string. So, an input like "cabbacbdbadbcabdaadcb" becomes "adcb" (keeping the last of each unique character). Then, with a string containing unique characters, that string's length is the answer.

If, for some reason, you needed the unique-character string and you needed it in the original order, you would have to reverse the original string before stripping away duplicate characters (and then reverse it again when you're done). This would require either a third-party library, StringBuffer, or a loop.

like image 171
Brian S Avatar answered Sep 20 '22 02:09

Brian S