Determine if String Halves Are Alike: Vowel Counting
LeetCode 1704. Determine if String Halves Are Alike gives you a string of even length and asks whether the first half and the second half contain the same number of vowels. Vowels are the characters a, e, i, o, u and their uppercase counterparts. If the vowel counts match, the halves are "alike" and you return True. Otherwise, return False.
This is a clean exercise in string traversal and counting, two building blocks that appear in dozens of other problems.
Approach: single pass vowel counting
Split the string at the midpoint, then count the vowels in each half. You can do this with a single pass through the string. For each character in the first half, increment a counter when it is a vowel. For each character in the second half, decrement the same counter. If the counter is zero at the end, both halves had the same number of vowels.
def halves_are_alike(s: str) -> bool:
vowels = set("aeiouAEIOU")
mid = len(s) // 2
count = 0
for i in range(mid):
if s[i] in vowels:
count += 1
if s[mid + i] in vowels:
count -= 1
return count == 0
The key insight is that you do not need to build two separate counts and compare them. A single counter that increments for the first half and decrements for the second half achieves the same thing. If it ends at zero, the counts were equal.
Visual walkthrough
Step 1: Split the string in half
"book""bo""ok"The string "book" has length 4, so the midpoint is index 2. The first half is "bo" and the second half is "ok".
Step 2: Count vowels in the first half
Walk through "bo". The character "b" is not a vowel. The character "o" is a vowel. That gives us 1 vowel in the first half.
Step 3: Count vowels in the second half
Walk through "ok". The character "o" is a vowel. The character "k" is not a vowel. That gives us 1 vowel in the second half.
Step 4: Compare the counts
Both halves contain exactly 1 vowel. Since count_a equals count_b, the string halves are alike. Return True.
The string "book" splits into "bo" and "ok". Each half contains exactly one vowel (o), so the halves are alike.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Single pass with counter | O(n) | O(1) |
You visit each character exactly once, and the vowel set has a fixed size of 10 characters. The space usage does not grow with the input.
Building blocks
1. Vowel membership check
Testing whether a character belongs to a small fixed set is one of the most common micro-operations in string problems. A set lookup keeps this at O(1).
vowels = set("aeiouAEIOU")
if ch in vowels:
# handle vowel
You will reach for this same snippet in problems like "reverse vowels of a string," "count vowels in a range," and "remove vowels from a string."
2. Increment/decrement counter for balance checks
Instead of maintaining two separate counts and comparing them at the end, a single counter that goes up for one group and down for the other tells you whether they are balanced. This pattern shows up whenever you need to verify that two halves, two strings, or two categories have equal frequency of something.
count = 0
for item in first_group:
if condition(item):
count += 1
for item in second_group:
if condition(item):
count -= 1
return count == 0
The same idea powers problems like Valid Anagram, where you count characters up for one string and down for the other.
Edge cases
- All vowels: A string like
"aeiou"has odd length and would not appear as input (the problem guarantees even length). But"aeio"splits into"ae"(2 vowels) and"io"(2 vowels), returningTrue. - No vowels: A string like
"bcdf"has 0 vowels in both halves. Zero equals zero, so the halves are alike. - Mixed case: The problem includes uppercase vowels. A string like
"AbCd"hasAas a vowel in the first half and no vowels in the second half, returningFalse. Make sure your vowel set includes both cases. - Length 2: The shortest possible input.
"ab"splits into"a"(1 vowel) and"b"(0 vowels), returningFalse.
From understanding to recall
This problem is simple enough to solve on sight, but the building blocks inside it, vowel membership checks and balance counters, carry over to much harder problems. When you see a sliding window problem that tracks vowel counts across a moving range, you want these pieces to be automatic.
Spaced repetition locks that in. CodeBricks breaks down problems like this into their reusable components and drills them at increasing intervals. You practice the vowel set pattern and the balance counter pattern separately, so that when they appear together in a harder problem, you recognize both pieces instantly.
Related posts
- Two Sum - another pattern that uses a set for O(1) lookups
- Valid Anagram - frequency counting on strings using the same increment/decrement technique
- Contains Duplicate - set-based membership checking pattern