Determine if String Halves Are Alike
EasyUpdated: Aug 2, 2025
Practice on:
Problem
You are given a string s of even length. Split this string into two halves of equal lengths, and let a be the first half and b be the second half.
Two strings are alike if they have the same number of vowels ('a',
'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'). Notice that
s contains uppercase and lowercase letters.
Return true ifa andb arealike. Otherwise, return false.
Examples
Example 1
Input: s = "book"
Output: true
Explanation: a = "b _o_ " and b = "_o_ k". a has 1 vowel and b has 1 vowel. Therefore, they are alike.
Example 2
Input: s = "textbook"
Output: false
Explanation: a = "t _e_ xt" and b = "b _oo_ k". a has 1 vowel whereas b has 2. Therefore, they are not alike.
Notice that the vowel o is counted twice.
Constraints
2 <= s.length <= 1000s.lengthis even.sconsists of uppercase and lowercase letters.
Solution
Method 1 – Vowel Counting
Intuition
If the two halves of the string have the same number of vowels, they are alike. We can count vowels in each half and compare.
Approach
- Define a set of vowels (both lowercase and uppercase).
- Split the string into two halves.
- Count the number of vowels in each half.
- Return true if the counts are equal, else false.
Code
C++
class Solution {
public:
bool halvesAreAlike(string s) {
string v = "aeiouAEIOU";
int n = s.size(), cnt1 = 0, cnt2 = 0;
for (int i = 0; i < n / 2; ++i) if (v.find(s[i]) != string::npos) ++cnt1;
for (int i = n / 2; i < n; ++i) if (v.find(s[i]) != string::npos) ++cnt2;
return cnt1 == cnt2;
}
};
Go
func halvesAreAlike(s string) bool {
vowels := "aeiouAEIOU"
n := len(s)
cnt1, cnt2 := 0, 0
for i := 0; i < n/2; i++ {
if strings.ContainsRune(vowels, rune(s[i])) {
cnt1++
}
}
for i := n / 2; i < n; i++ {
if strings.ContainsRune(vowels, rune(s[i])) {
cnt2++
}
}
return cnt1 == cnt2
}
Java
class Solution {
public boolean halvesAreAlike(String s) {
String v = "aeiouAEIOU";
int n = s.length(), cnt1 = 0, cnt2 = 0;
for (int i = 0; i < n / 2; ++i) if (v.indexOf(s.charAt(i)) != -1) ++cnt1;
for (int i = n / 2; i < n; ++i) if (v.indexOf(s.charAt(i)) != -1) ++cnt2;
return cnt1 == cnt2;
}
}
Kotlin
class Solution {
fun halvesAreAlike(s: String): Boolean {
val v = "aeiouAEIOU"
val n = s.length
var cnt1 = 0
var cnt2 = 0
for (i in 0 until n / 2) if (v.contains(s[i])) cnt1++
for (i in n / 2 until n) if (v.contains(s[i])) cnt2++
return cnt1 == cnt2
}
}
Python
class Solution:
def halvesAreAlike(self, s: str) -> bool:
v = set('aeiouAEIOU')
n = len(s)
cnt1 = sum(1 for c in s[:n//2] if c in v)
cnt2 = sum(1 for c in s[n//2:] if c in v)
return cnt1 == cnt2
Rust
impl Solution {
pub fn halves_are_alike(s: String) -> bool {
let v = "aeiouAEIOU".chars().collect::<std::collections::HashSet<_>>();
let n = s.len();
let s = s.chars().collect::<Vec<_>>();
let cnt1 = s[..n/2].iter().filter(|c| v.contains(c)).count();
let cnt2 = s[n/2..].iter().filter(|c| v.contains(c)).count();
cnt1 == cnt2
}
}
TypeScript
class Solution {
halvesAreAlike(s: string): boolean {
const v = new Set('aeiouAEIOU');
const n = s.length;
let cnt1 = 0, cnt2 = 0;
for (let i = 0; i < n / 2; ++i) if (v.has(s[i])) ++cnt1;
for (let i = n / 2; i < n; ++i) if (v.has(s[i])) ++cnt2;
return cnt1 === cnt2;
}
}
Complexity
- ⏰ Time complexity:
O(n), where n is the length of s. We scan the string once. - 🧺 Space complexity:
O(1), as we use only a constant amount of extra space.