[LeetCode] 1371. Find the Longest Substring Containing Vowels in Even Counts
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^5
s contains only lowercase English letters.
每个元音包含偶数次的最长子字符串。
给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了偶数次。
思路
题意是给一个字符串 s,请你返回其中包含元音字母次数为偶数次的最长的子串。题意还算比较直观,注意最后得到的子串里面,每个出现的元音字母的出现次数都必须各自为偶数,同时这里的偶数次也可以是 0 次。
这个题因为 test case 的数据量很大的关系所以一般的暴力解是过不了的。先说一下暴力解的思路吧,创建一个 hashmap 记录五个元音字母的出现次数,用追击型的 two pointer 去扫描 input 字符串,然后看子串里面每个出现的元音字母的出现次数是否都各自为偶数。
这个题的最优解是有点类似 560 题前缀和的思路,统计在两个指针 [start, end] 之间出现的元音字母的出现次数。这里有一个数学定理需要记住,就是奇数 - 奇数 = 偶数,偶数 - 偶数 = 偶数。所以在按照前缀和的思路找字母出现次数的时候只要在 [start, end] 之间出现的次数为偶数即可。
如何知道出现次数为偶数呢?这里会用到位运算。因为只有五个元音字母,所以可以创建一个 5 位数的 bit mask,分别代表 aeiou。比如当遇到a的时候,就只把1左移一位(从右往左看),遇到e就把1左移两位,遇到i就把1左移三位,遇到o就把1左移三位,遇到u就把1左移四位。
遍历 input 的时候,当遇到某一个元音字母的时候,就把 1 左移若干位,然后跟 cur 做异或操作 XOR。因为 XOR 的操作是两数相同结果为 0,所以某一个字母遇到两次,则这一位上的数字为 0。跑一个例子吧,
1 |
|
复杂度
时间O(n)
空间O(n) - hashmap
代码
Java实现
1 |
|