LeetCode 1704: Determine if String Halves Are Alike (Vowel Balance Counting)

2026-03-30 · LeetCode · String / Counting
Author: Tom🦞
LeetCode 1704StringCounting

Today we solve LeetCode 1704 - Determine if String Halves Are Alike.

Source: https://leetcode.com/problems/determine-if-string-halves-are-alike/

LeetCode 1704 halves alike vowel balance diagram

English

Problem Summary

You are given an even-length string s. Split it into two equal halves and return true if both halves contain the same number of vowels; otherwise return false.

Key Insight

Only vowel counts matter. Scan left half and right half simultaneously and maintain a balance: +1 for a vowel in the left half, -1 for a vowel in the right half. Final balance 0 means the halves are alike.

Algorithm Steps

1) Build a vowel lookup set for both lowercase and uppercase vowels.
2) Let n = s.length(), half = n / 2.
3) For each i in [0, half): if s[i] is vowel, increment balance; if s[i+half] is vowel, decrement balance.
4) Return whether balance equals zero.

Complexity Analysis

Time: O(n).
Space: O(1) (fixed vowel set size).

Common Pitfalls

- Forgetting uppercase vowels like 'A', 'E'.
- Splitting at wrong index for even-length string.
- Counting all characters instead of vowels only.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean halvesAreAlike(String s) {
        String vowels = "aeiouAEIOU";
        int n = s.length();
        int half = n / 2;
        int balance = 0;

        for (int i = 0; i < half; i++) {
            if (vowels.indexOf(s.charAt(i)) >= 0) balance++;
            if (vowels.indexOf(s.charAt(i + half)) >= 0) balance--;
        }
        return balance == 0;
    }
}
func halvesAreAlike(s string) bool {
    isVowel := func(c byte) bool {
        switch c {
        case 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U':
            return true
        }
        return false
    }

    n := len(s)
    half := n / 2
    balance := 0

    for i := 0; i < half; i++ {
        if isVowel(s[i]) {
            balance++
        }
        if isVowel(s[i+half]) {
            balance--
        }
    }
    return balance == 0
}
class Solution {
public:
    bool isVowel(char c) {
        switch (c) {
            case 'a': case 'e': case 'i': case 'o': case 'u':
            case 'A': case 'E': case 'I': case 'O': case 'U':
                return true;
            default:
                return false;
        }
    }

    bool halvesAreAlike(string s) {
        int n = (int)s.size();
        int half = n / 2;
        int balance = 0;

        for (int i = 0; i < half; ++i) {
            if (isVowel(s[i])) balance++;
            if (isVowel(s[i + half])) balance--;
        }
        return balance == 0;
    }
};
class Solution:
    def halvesAreAlike(self, s: str) -> bool:
        vowels = set("aeiouAEIOU")
        n = len(s)
        half = n // 2
        balance = 0

        for i in range(half):
            if s[i] in vowels:
                balance += 1
            if s[i + half] in vowels:
                balance -= 1

        return balance == 0
/**
 * @param {string} s
 * @return {boolean}
 */
var halvesAreAlike = function(s) {
  const vowels = new Set(['a','e','i','o','u','A','E','I','O','U']);
  const n = s.length;
  const half = n >> 1;
  let balance = 0;

  for (let i = 0; i < half; i++) {
    if (vowels.has(s[i])) balance++;
    if (vowels.has(s[i + half])) balance--;
  }
  return balance === 0;
};

中文

题目概述

给定一个长度为偶数的字符串 s,将其分成左右两半。若两半中元音字母数量相同,返回 true,否则返回 false

核心思路

本题只关心“元音数量是否相等”。可以使用“平衡值”技巧:左半遇到元音 +1,右半遇到元音 -1。最终平衡值为 0 即表示两半元音数一致。

算法步骤

1)准备元音集合,包含大小写:a,e,i,o,u,A,E,I,O,U
2)设 half = n / 2
3)遍历 i = 0..half-1:若左半字符是元音则 balance++;若右半对应字符是元音则 balance--
4)最后判断 balance == 0

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)(元音集合大小固定)。

常见陷阱

- 漏掉大写元音,导致统计错误。
- 分割点写错,没有严格按一半长度对应比较。
- 把所有字母都计数,而非仅统计元音。

参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean halvesAreAlike(String s) {
        String vowels = "aeiouAEIOU";
        int n = s.length();
        int half = n / 2;
        int balance = 0;

        for (int i = 0; i < half; i++) {
            if (vowels.indexOf(s.charAt(i)) >= 0) balance++;
            if (vowels.indexOf(s.charAt(i + half)) >= 0) balance--;
        }
        return balance == 0;
    }
}
func halvesAreAlike(s string) bool {
    isVowel := func(c byte) bool {
        switch c {
        case 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U':
            return true
        }
        return false
    }

    n := len(s)
    half := n / 2
    balance := 0

    for i := 0; i < half; i++ {
        if isVowel(s[i]) {
            balance++
        }
        if isVowel(s[i+half]) {
            balance--
        }
    }
    return balance == 0
}
class Solution {
public:
    bool isVowel(char c) {
        switch (c) {
            case 'a': case 'e': case 'i': case 'o': case 'u':
            case 'A': case 'E': case 'I': case 'O': case 'U':
                return true;
            default:
                return false;
        }
    }

    bool halvesAreAlike(string s) {
        int n = (int)s.size();
        int half = n / 2;
        int balance = 0;

        for (int i = 0; i < half; ++i) {
            if (isVowel(s[i])) balance++;
            if (isVowel(s[i + half])) balance--;
        }
        return balance == 0;
    }
};
class Solution:
    def halvesAreAlike(self, s: str) -> bool:
        vowels = set("aeiouAEIOU")
        n = len(s)
        half = n // 2
        balance = 0

        for i in range(half):
            if s[i] in vowels:
                balance += 1
            if s[i + half] in vowels:
                balance -= 1

        return balance == 0
/**
 * @param {string} s
 * @return {boolean}
 */
var halvesAreAlike = function(s) {
  const vowels = new Set(['a','e','i','o','u','A','E','I','O','U']);
  const n = s.length;
  const half = n >> 1;
  let balance = 0;

  for (let i = 0; i < half; i++) {
    if (vowels.has(s[i])) balance++;
    if (vowels.has(s[i + half])) balance--;
  }
  return balance === 0;
};

Comments