Vowel Frequency Analysis — Problem Statement & Solution Guide
Problem Description
Given an array of lowercase strings vowelStrings, produce an integer array result where result[i] equals the count of characters 'a','e','i','o','u' appearing in vowelStrings[i]. The order of counts must correspond to the original order of strings. Return result.
DSA Pattern Breakdown
DSA Pattern Breakdown
"Vowel Frequency Analysis"
WHY DOES IT MATTER?
Counting specific characters is a classic linear‑scan pattern that appears in text processing, validation, and compression tasks; mastering it builds intuition for designing O(n) solutions over brute‑force nested loops.
OPTIMIZATION CHALLENGE
The key insight is replacing a per‑character O(V) vowel comparison with O(1) set membership, typically via a hash set or a boolean array indexed by character code, thus collapsing the inner loop’s constant factor.
REAL-WORLD CONNECTION
Think of a log‑aggregation service that tags each log line with the number of error‑keywords it contains; the service must scan each line once and update metrics in real time, mirroring the per‑string vowel count.
During an interview, pre‑declare a constant vowel lookup (e.g., const vowels = new Set(['a','e','i','o','u'])); then loop through each string and increment a counter when vowels.has(ch); this signals you think about constant‑time checks and clean code organization.
COMPLEXITY AT A GLANCE
O(N·L)O(1) additionalCore Theory — Why This Approach?
The problem reduces to counting occurrences of a fixed small alphabet (the five vowels) within each string of an input array. A naïve solution might iterate over each string and, for each character, check against each vowel using a nested loop, leading to O(N*L*V) time where V=5, which is still linear but incurs unnecessary constant factor overhead. More importantly, if a candidate attempts to recompute vowel sets or uses expensive string operations like split or regex for each character, the hidden costs can explode on large inputs (e.g., millions of characters). The optimal paradigm leverages a single pass per string combined with O(1) membership testing via a hash set or boolean lookup table, collapsing the inner vowel‑check loop into a constant‑time operation. This yields a clean O(N·L) overall runtime while using only O(1) auxiliary space beyond the result array.
Interview Questions on This Problem
Q1How would you modify the solution if the input could contain uppercase letters and you needed to count both uppercase and lowercase vowels?
Normalize each character to lowercase (or uppercase) before the membership test, or expand the vowel set to include both cases; the algorithmic complexity remains O(N·L) with only a constant‑time check per character.
Q2If the array size is extremely large and the result needs to be streamed to a client, what changes would you make to the algorithm?
Process each string sequentially and emit its count immediately, avoiding storing the entire result array in memory; this turns the solution into an O(1) additional space streaming algorithm while preserving O(N·L) time.
Q3Can you compute the total number of vowels across all strings without storing per‑string counts?
Yes—maintain a single accumulator that adds the count from each string as you iterate; this reduces space to O(1) and still runs in O(N·L) time.
Examples
Input
["apple","banana","cherry"]
Output
[2,3,1]
Explanation: apple contains 'a' and 'e' →2; banana contains three 'a' →3; cherry contains 'e' →1.
Input
["aeiou","bcdfg",""]
Output
[5,0,0]
Explanation: 'aeiou' has all five vowels →5; 'bcdfg' has none →0; empty string has none →0.
Input
["queue","rhythm","aeaeae"]
Output
[4,0,6]
Explanation: 'queue' contains u,e,u,e →4; 'rhythm' contains no vowel →0; 'aeaeae' alternates a and e six times →6.
Constraints
- 1 <= vowelStrings.length <= 100000
- 0 <= vowelStrings[i].length <= 10000
- All characters are lowercase English letters
- Total number of characters across all strings does not exceed 1000000
Optimal Approach & Strategy
Use a hash set or boolean array for vowel lookup so each character is checked in O(1) time, scanning each string once.
Brute Force Approach
Iterate each string and for each character, compare it against each vowel using a nested loop, leading to unnecessary repeated checks.
Verified Code Solutions
function vowelFrequency(vowelStrings) {
const result = [];
for (const str of vowelStrings) {
let count = 0;
for (const ch of str) {
if ("aeiou".includes(ch)) {
++count;
}
}
result.push(count);
}
return result;
}
// Driver code for testing
let input = ["apple","banana","cherry"];
let output = vowelFrequency(input);
console.log(output);#include <iostream>
#include <vector>
#include <string>
std::vector<int> vowelFrequency(const std::vector<std::string>& vowelStrings) {
std::vector<int> result;
for (const auto& str : vowelStrings) {
int count = 0;
for (char c : str) {
switch(c) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
++count;
}
}
result.push_back(count);
}
return result;
}
int main() {
std::vector<std::string> input = {"apple","banana","cherry"};
std::vector<int> output = vowelFrequency(input);
for (int cnt : output) {
std::cout << cnt << " ";
}
return 0;
}import java.util.*;
public class VowelFrequency {
public static int[] vowelFrequency(String[] vowelStrings) {
int[] result = new int[vowelStrings.length];
for (int i = 0; i < vowelStrings.length; i++) {
int count = 0;
for (char c : vowelStrings[i].toCharArray()) {
if ("aeiou".indexOf(c) != -1) {
++count;
}
}
result[i] = count;
}
return result;
}
public static void main(String[] args) {
String[] input = {"apple","banana","cherry"};
int[] output = vowelFrequency(input);
System.out.println(Arrays.toString(output));
}
}def vowel_frequency(vowel_strings):
result = []
for s in vowel_strings:
count = sum(1 for c in s if c in "aeiou")
result.append(count)
return result
# Driver code for testing
input_strings = ["apple","banana","cherry"]
output = vowel_frequency(input_strings)
print(output)function vowelFrequency(vowelStrings) {
const result = [];
for (const str of vowelStrings) {
let count = 0;
for (const ch of str) {
if ("aeiou".includes(ch)) {
++count;
}
}
result.push(count);
}
return result;
}
// Driver code for testing
let input = ["apple","banana","cherry"];
let output = vowelFrequency(input);
console.log(output);Asked in Top Tech Interviews
Solve in Interative Editor
Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.