惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
有赞技术团队
有赞技术团队
V
Visual Studio Blog
T
The Blog of Author Tim Ferriss
爱范儿
爱范儿
Vercel News
Vercel News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Y
Y Combinator Blog
Blog — PlanetScale
Blog — PlanetScale
D
DataBreaches.Net
美团技术团队
Microsoft Security Blog
Microsoft Security Blog
大猫的无限游戏
大猫的无限游戏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
酷 壳 – CoolShell
酷 壳 – CoolShell
GbyAI
GbyAI
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
The Cloudflare Blog
宝玉的分享
宝玉的分享
V
V2EX
Microsoft Azure Blog
Microsoft Azure Blog

博客园 - Grandyang

[LeetCode] 1375. Number of Times Binary String Is Prefix-Aligned 二进制字符串前缀一致的次数 [LeetCode] 1374. Generate a String With Characters That Have Odd Counts 生成每种字符都是奇数个的字符串 [LeetCode] 1373. Maximum Sum BST in Binary Tree 二叉搜索子树的最大键值和 [LeetCode] 1372. Longest ZigZag Path in a Binary Tree 二叉树中的最长交错路径 [LeetCode] 1370. Increasing Decreasing String 上升下降字符串 [LeetCode] 1368. Minimum Cost to Make at Least One Valid Path in a Grid 使网格图至少有一条有效路径的最小代价 [LeetCode] 1367. Linked List in Binary Tree 二叉树中的链表 [LeetCode] 1366. Rank Teams by Votes 通过投票对团队排名 [LeetCode] 1365. How Many Numbers Are Smaller Than the Current Number 有多少小于当前数字的数字 [LeetCode] 1363. Largest Multiple of Three 形成三的最大倍数 [LeetCode] 1362. Closest Divisors 最接近的因数 [LeetCode] 1361. Validate Binary Tree Nodes 验证二叉树 [LeetCode] 1360. Number of Days Between Two Dates 日期之间隔几天 [LeetCode] 1359. Count All Valid Pickup and Delivery Options 有效的快递序列数目 [LeetCode] 1358. Number of Substrings Containing All Three Characters 包含所有三种字符的子字符串数目 [LeetCode] 1357. Apply Discount Every n Orders 每隔n个顾客打折 [LeetCode] 1356. Sort Integers by The Number of 1 Bits 根据数字二进制下1 的数目排序 [LeetCode] 1354. Construct Target Array With Multiple Sums 多次求和构造目标数组 [LeetCode] 1353. Maximum Number of Events That Can Be Attended 最多可以参加的会议数目 [LeetCode] 1352. Product of the Last K Numbers 最后 K 个数的乘积 [LeetCode] 1351. Count Negative Numbers in a Sorted Matrix 统计有序矩阵中的负数 [LeetCode] 1349. Maximum Students Taking Exam 参加考试的最大学生数
[LeetCode] 1371. Find the Longest Substring Containing Vo...
Grandyang · 2025-05-27 · via 博客园 - Grandyang

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。这道题的难点还是在于如何统计元音字母的个数,并且判断他们是否都为偶数,大多数人可能第一时间就会考虑用个 HashMap 来统计元音字母出现的个数,然后再分别判断是不是偶数个。其实这里我们对具体的个数并不关心,只要知道是不是偶数,实际上每个元音只有奇数和偶数两种状态,总共五个元音,则共有 2^5 = 32 种状态,那么正好可以使用位运算的思想来记录状态,五个元音各用一个二进制的位来记录状态,0即为偶数,1为奇数,这里a在最低位,其次按顺序是 e,i,o,u。则二进制 00000 就表示五个元音全是偶数,00011 就表示元音a和e为奇数,这里每一位对应的十进制数分别为1,2,4,8,16。这样范围为 [0, i] 内的子串的元音奇偶数状态就知道了,同时还要记录下第一个出现非0状态的位置,当下次再次出现相同的状态码时,比如 [0, j] 范围内的子串也是相同的状态,则范围 [i, j] 内的子串必定元音都是偶数个的,这样可以快速来更新结果 res。

明白了这点后,可以来写代码了,这里的状态码用一个整型数 mask 来表示,同时为了更方便的取出每个元音位对应的十进制数,可以用一个 HashMap 来建立映射。然后还需要一个状态值和下标之间的映射,这里可以用 HashMap,或者一个大小为 32 的数组 mask2idx 就行,因为状态码是不会超过32的整型数,初始化值为 -1。然后可以开始遍历了,将遍历到的字母到 vowelMap 中取值,如果是元音,就会取到对应的非零值,然后 mask 异或上这个值,此时若 mask 不为0,且当前的 mask 值之前并没有出现过,即在 mask2idx 中的值是 -1,此时就更新其值为i。然后用 i - mask2idx[mask] 来更新结果 res 即可,参见代码如下:


class Solution {
public:
    int findTheLongestSubstring(string s) {
        int res = 0, mask = 0, n = s.size();
        unordered_map<char, int> vowelMap{{'a', 1}, {'e', 2}, {'i', 4}, {'o', 8}, {'u', 16}};
        vector<int> mask2idx(32, -1);
        for (int i = 0; i < s.size(); ++i) {
            mask ^= vowelMap[s[i]];
            if (mask != 0 && mask2idx[mask] == -1) {
                mask2idx[mask] = i;
            }
            res = max(res, i - mask2idx[mask]);
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1371

参考资料:

https://leetcode.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/description/

https://leetcode.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/editorial/

https://leetcode.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/solutions/534135/c-java-with-picture/

LeetCode All in One 题目讲解汇总(持续更新中...)