3
\$\begingroup\$

Checking if all five vowels are present in a string.

String phrase = "Hello, how are you keeping?";
String vowelsInPhrase = phrase.toLowerCase().replaceAll("[^aeiou]", "");
String temp = vowelsInPhrase;
String usedVowels = "";
    while(temp.length() > 0){
        usedVowels += temp.substring(0, 1);
        temp = temp.replaceAll(temp.substring(0, 1), "");
    }
    if(usedVowels.length() == 5){
        result += "At least one occurrence of each vowel.\n";
    }

Does anyone have a better solution?? I am thinking some sort of pattern to check if each required character has appeared one or more times but I don't know if it is possible. This would save using the while loop.

Something like this is what I was thinking:

String pattern = "[[a]+[e]+[i]+[o]+[u]+]";
if(usedVowels.matches(pattern){
        result += "At least one occurrence of each vowel.\n";
    }
\$\endgroup\$
3
\$\begingroup\$

You can do this entirely with regular expressions by using match groups. You can create a pattern matcher like this:

Matcher m = Pattern.compile("(?:(a)|(e)|(i)|(o)|(u)|.)+", Pattern.CASE_INSENSITIVE)
                   .matcher("Hello, how are you keeping?");

This operates based on how subgroup capture works. If no matches are found, the groups will be null, otherwise, they'll include the first match. This holds even if they're matched multiple times. Therefore, you can use the following code to test if all the vowels are found:

if (m.matches() &&
    m.group(1) != null &&
    m.group(2) != null &&
    m.group(3) != null &&
    m.group(4) != null &&
    m.group(5) != null) {
    System.out.println("All vowels matched!");
} else {
    System.out.println("Not all vowels matched.");
}

See some running examples of that code here. (Thanks to rolfl for the expanded examples!)

\$\endgroup\$
  • 2
    \$\begingroup\$ Nice, I played a bit with your solution here... feel free to pull what you want for your answer: Ideone \$\endgroup\$ – rolfl Feb 5 '15 at 19:45
  • \$\begingroup\$ @rolfl Thanks much! I edited your ideone snippet just a little and linked to that version in my answer. I think I'll keep the code I've directly included, though, just because I think it's simple and to the point. \$\endgroup\$ – Alexis King Feb 5 '15 at 19:50
  • \$\begingroup\$ Thanks guys looks good.... Shur if you only learn one thing a day then at least your heading in the right direction :P \$\endgroup\$ – kfcobrien Feb 5 '15 at 19:56
3
\$\begingroup\$

Any solution to this would have to be at least O(n), because worst case you're going to have to check every character in the String.

A very simple solution to this problem is to create an array of 5 booleans, corresponding to the 5 vowels. Then iterate through the string, and if you see a vowel, mark that index (e.g. a = 0, e = 1, etc.) as true. As soon as all 5 are true, return true, as all the vowels occur (assuming that you don't care if they occur more than once).

That has the same time complexity as your regex solution and is far simpler to implement/read/maintain.

You could also sort the string and then binary search for each of the required characters. This has a higher upfront cost (nlogn for the sort, logn for each binary search), but if you're making multiple queries on the same string, might be more efficient in the long run.

\$\endgroup\$
  • \$\begingroup\$ again another decent solution :) It amazes me how people have all got their own little strategies :) \$\endgroup\$ – kfcobrien Feb 5 '15 at 19:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.