Balanced Vowel Casing — Problem Statement & Solution Guide
Problem Description
Given a string s, count the vowels that appear in uppercase form (A, E, I, O, U) and the vowels that appear in lowercase form (a, e, i, o, u). Ignore all other characters. If the two counts are equal, output "YES"; otherwise output "NO". The input consists of a single line containing the string s. The output is a single word, either "YES" or "NO".
DSA Pattern Breakdown
DSA Pattern Breakdown
"Balanced Vowel Casing"
WHY DOES IT MATTER?
Counting specific character categories in a single pass is a classic pattern that appears in validation, parsing, and analytics tasks. Mastering it helps candidates write concise, efficient code without unnecessary data structures.
OPTIMIZATION CHALLENGE
The key insight is recognizing that the set of target characters (10 vowel forms) is constant, allowing direct character comparisons instead of generic hash‑map lookups, which reduces both time overhead and memory footprint.
REAL-WORLD CONNECTION
Think of a log‑processing service that needs to tally error codes of different severity levels in real time; it must scan each log entry once and update counters, mirroring the vowel‑casing balance check.
During an interview, write the character‑checking logic as a simple switch or lookup string (e.g., "AEIOU" and "aeiou") to avoid typo‑prone multiple if‑else statements and to demonstrate clean, readable code.
COMPLEXITY AT A GLANCE
O(n)O(1)Core Theory — Why This Approach?
The problem reduces to a single linear scan of the input string, classifying each character as an uppercase vowel, a lowercase vowel, or irrelevant. By maintaining two counters—one for uppercase vowels and one for lowercase vowels—we can determine the balance in O(n) time, where n is the length of the string. This approach leverages the concept of frequency counting, a fundamental technique in string processing that avoids the overhead of auxiliary data structures like hash maps when the set of target characters is fixed and small.
A naive solution might attempt to count each vowel separately using multiple passes or nested loops, which would inflate the time complexity to O(n * k) where k is the number of vowel cases (10). While still linear for small k, such redundancy becomes problematic when the input size grows to millions of characters, especially under strict time limits. The optimal paradigm—single-pass counting—eliminates repeated work, ensures constant extra space, and scales gracefully with input size.
Interview Questions on This Problem
Q1How would you modify the solution to also handle consonants and determine if the number of uppercase letters equals the number of lowercase letters overall?
Extend the counters to track uppercase and lowercase letters for all alphabetic characters, not just vowels. During the single pass, increment the appropriate counter for each alphabetic character based on its case, then compare the two totals at the end.
Q2If the input string could be extremely large (e.g., streamed from a file), how would you adapt your algorithm to work with limited memory?
Process the string as a stream, reading it chunk by chunk and updating the two counters on the fly. Since only two integer variables are needed, memory usage remains O(1) regardless of the input size.
Q3Can you design a solution that works for Unicode strings where vowels may appear in accented forms (e.g., á, É)?
Create a normalized set of Unicode code points representing both accented and unaccented vowels for each case, then during the scan check membership using a hash set. The algorithm remains O(n) but requires a larger constant-time lookup table.
Examples
Input
AeIoU
Output
NO
Explanation: Uppercase vowels: A, E, I, O, U → 5. Lowercase vowels: none → 0. 5 ≠ 0, so the answer is NO.
Input
aEiO
Output
YES
Explanation: Uppercase vowels: E, O → 2. Lowercase vowels: a, i → 2. 2 = 2, so the answer is YES.
Input
HelloWorld
Output
NO
Explanation: Uppercase vowels: none. Lowercase vowels: e, o, o → 3. 0 ≠ 3, so the answer is NO.
Input
AaEeIiOoUu
Output
YES
Explanation: Uppercase vowels: A, E, I, O, U → 5. Lowercase vowels: a, e, i, o, u → 5. 5 = 5, so the answer is YES.
Constraints
- 1 <= |s| <= 100000
- s contains only printable ASCII characters
- The comparison is case‑sensitive
- The solution must run in O(|s|) time and O(1) additional space
Optimal Approach & Strategy
Perform a single linear scan, using two integer counters and direct character comparisons to update them on the fly, achieving O(n) time with O(1) extra space.
Brute Force Approach
Iterate over the string multiple times, once for each vowel case, counting occurrences separately; this leads to redundant passes and higher constant factors.
Verified Code Solutions
function balancedVowelCasing(s) {
if (typeof s !== 'string') {
throw new Error('Input must be a string');
}
let upperVowels = 0;
let lowerVowels = 0;
for (let char of s) {
if ('AEIOU'.includes(char.toUpperCase())) {
if (char === char.toUpperCase()) {
upperVowels++;
} else {
lowerVowels++;
}
}
}
return upperVowels === lowerVowels;
}class Solution {
public:
bool balancedVowelCasing(string s) {
if (s.empty() || typeid(s).name() != typeid(string).name()) {
throw invalid_argument('Input must be a string');
}
int upperVowels = 0;
int lowerVowels = 0;
for (char c : s) {
if ('AEIOU'.find(c) != string::npos) {
if (isupper(c)) {
upperVowels++;
} else {
lowerVowels++;
}
}
}
return upperVowels == lowerVowels;
}
};public class Solution {
public boolean balancedVowelCasing(String s) {
if (s == null || s.getClass() != String.class) {
throw new IllegalArgumentException('Input must be a string');
}
int upperVowels = 0;
int lowerVowels = 0;
for (char c : s.toCharArray()) {
if ('AEIOU'.toUpperCase().indexOf(c) != -1) {
if (Character.isUpperCase(c)) {
upperVowels++;
} else {
lowerVowels++;
}
}
}
return upperVowels == lowerVowels;
}
}def balanced_vowel_casing(s):
if not isinstance(s, str):
raise ValueError('Input must be a string')
upper_vowels = 0
lower_vowels = 0
for char in s:
if 'AEIOU'.casefold() in char:
if char.isupper():
upper_vowels += 1
else:
lower_vowels += 1
return upper_vowels == lower_vowelsfunction balancedVowelCasing(s) {
if (typeof s !== 'string') {
throw new Error('Input must be a string');
}
let upperVowels = 0;
let lowerVowels = 0;
for (let char of s) {
if ('AEIOU'.includes(char.toUpperCase())) {
if (char === char.toUpperCase()) {
upperVowels++;
} else {
lowerVowels++;
}
}
}
return upperVowels === lowerVowels;
}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.