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

推荐订阅源

S
Secure Thoughts
C
Check Point Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
月光博客
月光博客
博客园 - 【当耐特】
Jina AI
Jina AI
雷峰网
雷峰网
J
Java Code Geeks
腾讯CDC
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 叶小钗
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
The Register - Security
The Register - Security
罗磊的独立博客
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
有赞技术团队
有赞技术团队
The Hacker News
The Hacker News
Scott Helme
Scott Helme
T
The Blog of Author Tim Ferriss
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
The Exploit Database - CXSecurity.com
Vercel News
Vercel News
Cisco Talos Blog
Cisco Talos Blog
美团技术团队
B
Blog RSS Feed
L
LangChain Blog
大猫的无限游戏
大猫的无限游戏
SecWiki News
SecWiki News
Webroot Blog
Webroot Blog
N
News | PayPal Newsroom
D
Docker
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
W
WeLiveSecurity
C
CERT Recently Published Vulnerability Notes
L
Lohrmann on Cybersecurity
T
Tenable Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
阮一峰的网络日志
阮一峰的网络日志
I
Intezer
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

博客园 - Grandyang

[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 Vowels in Even Counts 每个元音包含偶数次的最长子字符串
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 题目讲解汇总(持续更新中...)