Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
Given the string s, return the size of the longest substring containing each vowel an even number of times. That is, 'a', 'e', 'i', 'o', and 'u' must appear an even number of times.
Example 1:
Input: s = "eleetminicoworoep" Output: 13 Explanation: The longest substring is "leetminicowor" which contains two each of the vowels: e, i and o and zero of the vowels: a and u.
Example 2:
Input: s = "leetcodeisgreat" Output: 5 Explanation: The longest substring is "leetc" which contains two e's.
Example 3:
Input: s = "bcbcbc" Output: 6 Explanation: In this case, the given string "bcbcbc" is the longest because all vowels: a, e, i, o and u appear zero times.
Constraints:
1 <= s.length <= 5 x 10^5s contains only lowercase English letters.Problem summary: Given the string s, return the size of the longest substring containing each vowel an even number of times. That is, 'a', 'e', 'i', 'o', and 'u' must appear an even number of times.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Bit Manipulation
"eleetminicoworoep"
"leetcodeisgreat"
"bcbcbc"
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1371: Find the Longest Substring Containing Vowels in Even Counts
class Solution {
public int findTheLongestSubstring(String s) {
String vowels = "aeiou";
int[] d = new int[32];
Arrays.fill(d, 1 << 29);
d[0] = 0;
int ans = 0, mask = 0;
for (int i = 1; i <= s.length(); ++i) {
char c = s.charAt(i - 1);
for (int j = 0; j < 5; ++j) {
if (c == vowels.charAt(j)) {
mask ^= 1 << j;
break;
}
}
ans = Math.max(ans, i - d[mask]);
d[mask] = Math.min(d[mask], i);
}
return ans;
}
}
// Accepted solution for LeetCode #1371: Find the Longest Substring Containing Vowels in Even Counts
func findTheLongestSubstring(s string) (ans int) {
vowels := "aeiou"
d := [32]int{}
for i := range d {
d[i] = 1 << 29
}
d[0] = 0
mask := 0
for i := 1; i <= len(s); i++ {
c := s[i-1]
for j := 0; j < 5; j++ {
if c == vowels[j] {
mask ^= 1 << j
break
}
}
ans = max(ans, i-d[mask])
d[mask] = min(d[mask], i)
}
return
}
# Accepted solution for LeetCode #1371: Find the Longest Substring Containing Vowels in Even Counts
class Solution:
def findTheLongestSubstring(self, s: str) -> int:
d = {0: -1}
ans = mask = 0
for i, c in enumerate(s):
if c in "aeiou":
mask ^= 1 << (ord(c) - ord("a"))
if mask in d:
j = d[mask]
ans = max(ans, i - j)
else:
d[mask] = i
return ans
// Accepted solution for LeetCode #1371: Find the Longest Substring Containing Vowels in Even Counts
struct Solution;
use std::collections::HashMap;
impl Solution {
fn find_the_longest_substring(s: String) -> i32 {
let mut mask = 0;
let mut hm: HashMap<u8, usize> = HashMap::new();
hm.insert(0, 0);
let mut res = 0;
for (i, c) in s.char_indices() {
if Self::vowel(c) != 0 {
mask ^= 1 << Self::vowel(c);
}
hm.entry(mask).or_insert(i + 1);
res = res.max(i + 1 - hm[&mask]);
}
res as i32
}
fn vowel(c: char) -> usize {
match c {
'a' => 1,
'e' => 2,
'i' => 3,
'o' => 4,
'u' => 5,
_ => 0,
}
}
}
#[test]
fn test() {
let s = "eleetminicoworoep".to_string();
let res = 13;
assert_eq!(Solution::find_the_longest_substring(s), res);
let s = "leetcodeisgreat".to_string();
let res = 5;
assert_eq!(Solution::find_the_longest_substring(s), res);
let s = "bcbcbc".to_string();
let res = 6;
assert_eq!(Solution::find_the_longest_substring(s), res);
}
// Accepted solution for LeetCode #1371: Find the Longest Substring Containing Vowels in Even Counts
function findTheLongestSubstring(s: string): number {
const vowels = 'aeiou';
const d: number[] = Array(32).fill(1 << 29);
d[0] = 0;
let [ans, mask] = [0, 0];
for (let i = 1; i <= s.length; i++) {
const c = s[i - 1];
for (let j = 0; j < 5; j++) {
if (c === vowels[j]) {
mask ^= 1 << j;
break;
}
}
ans = Math.max(ans, i - d[mask]);
d[mask] = Math.min(d[mask], i);
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
Sort the array in O(n log n), then scan for the missing or unique element by comparing adjacent pairs. Sorting requires O(n) auxiliary space (or O(1) with in-place sort but O(n log n) time remains). The sort step dominates.
Bitwise operations (AND, OR, XOR, shifts) are O(1) per operation on fixed-width integers. A single pass through the input with bit operations gives O(n) time. The key insight: XOR of a number with itself is 0, which eliminates duplicates without extra space.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.