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.");
}
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();
.
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 flagSo, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With