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.
For example:
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.
Input: s = "leetcodeisgreat" Output: 5 Explanation: The longest substring is "leetc" which contains two e's.
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^5 s contains only lowercase English letters.
A brute-force approach would involve checking every possible substring of the given string s
and verifying if it contains each vowel ('a', 'e', 'i', 'o', 'u') an even number of times. The substring with the maximum length that satisfies this condition would be the answer.
def longest_substring_naive(s):
max_len = 0
for i in range(len(s)):
for j in range(i, len(s)):
sub = s[i:j+1]
counts = {
'a': 0,
'e': 0,
'i': 0,
'o': 0,
'u': 0
}
for char in sub:
if char in counts:
counts[char] += 1
even = True
for vowel in counts:
if counts[vowel] % 2 != 0:
even = False
break
if even:
max_len = max(max_len, len(sub))
return max_len
O(n^3), where n is the length of the string s
. This is because there are O(n^2) possible substrings, and for each substring, we iterate through it to count the vowels, which takes O(n) time.
O(1), as we only use a constant amount of extra space to store the vowel counts.
A more efficient approach involves using bit manipulation to represent the state of vowel counts and a prefix state map to store the first occurrence of each state. This allows us to find the longest substring with even vowel counts in O(n) time.
def longest_substring_optimal(s):
state = 0
state_map = {0: -1}
max_len = 0
for i in range(len(s)):
if s[i] == 'a':
state ^= 1 << 0
elif s[i] == 'e':
state ^= 1 << 1
elif s[i] == 'i':
state ^= 1 << 2
elif s[i] == 'o':
state ^= 1 << 3
elif s[i] == 'u':
state ^= 1 << 4
if state in state_map:
max_len = max(max_len, i - state_map[state])
else:
state_map[state] = i
return max_len
O(n), where n is the length of the string s
. This is because we iterate through the string only once.
O(1), since the state_map
can have at most 2^5 = 32 entries, which is constant.