leetcode
leetcode 1251 ~ 1300
每个元音包含偶数次的最长子字符串

每个元音包含偶数次的最长子字符串

难度:

标签:

题目描述

代码结果

运行时间: 149 ms, 内存: 22.6 MB


/*
思路: Java Stream 不太适合处理这种带状态的任务。我们仍然可以使用传统的方式处理此问题,
通过位掩码表示元音的奇偶性,使用 HashMap 记录状态和索引。
*/

import java.util.HashMap;
import java.util.Map;

public class Solution {
    public int findTheLongestSubstring(String s) {
        int maxLength = 0;
        int mask = 0;
        Map<Integer, Integer> map = new HashMap<>();
        map.put(0, -1); // 初始状态,mask为0在位置-1
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                case 'a':
                    mask ^= 1 << 0;
                    break;
                case 'e':
                    mask ^= 1 << 1;
                    break;
                case 'i':
                    mask ^= 1 << 2;
                    break;
                case 'o':
                    mask ^= 1 << 3;
                    break;
                case 'u':
                    mask ^= 1 << 4;
                    break;
            }
            if (map.containsKey(mask)) {
                maxLength = Math.max(maxLength, i - map.get(mask));
            } else {
                map.put(mask, i);
            }
        }
        return maxLength;
    }
}

解释

方法:

本题的核心思想是使用位掩码来跟踪元音字母的出现次数的奇偶性。每个元音字母对应于位掩码中的一个位,如果该字母出现奇数次,相应的位为1,偶数次则为0。通过XOR操作更新位掩码,从而不需要直接计数。数组`st`用于存储从字符串开头到当前位置的所有字符的位掩码。如果在两个位置`i`和`j`(其中`i < j`)的位掩码相同,这意味着从`i+1`到`j`的子字符串中所有元音字母出现了偶数次。因此,问题转化为寻找最大的`j - i`,其中`st[j] == st[i]`。

时间复杂度:

O(n^2)

空间复杂度:

O(n)

代码细节讲解

🦆
在位掩码的方法中,为什么使用位异或操作来跟踪元音字母出现的次数?
位异或操作(XOR)非常适合于跟踪出现次数的奇偶性。在二进制中,XOR操作具有翻转特性:对同一个数值进行两次XOR操作会恢复原值。因此,每次字符出现时,通过对应位进行XOR操作,可以有效地切换该位的状态(从0到1或从1到0),直接反映该字符出现次数的奇偶变化。这种方法既节省了存储空间,又简化了计算过程。
🦆
如何确保位掩码数组`st`在初始化时正确地反映了字符串中每个位置的元音出现奇偶性?
位掩码数组`st`的初始化是将`st[0]`设置为0,表示一个空字符串的位掩码。该初始值表明此时没有任何字符被处理,所有元音字母的出现次数默认为偶数(即0次)。随后,遍历字符串中的每个字符,若该字符是元音,则根据元音字母到位掩码的映射来更新当前位掩码,使用XOR操作反映其出现次数的变化。这种逐步构建保证了数组在每个位置上都正确反映了到该位置为止所有元音字母的出现奇偶性。
🦆
题解中提到如果`st[j] == st[i]`则从`i+1`到`j`的子字符串中所有元音字母出现了偶数次,能否详细解释这种情况为什么成立?
当两个位置的位掩码相同,即`st[j] == st[i]`,这表明从字符串的开始到位置`i`和到位置`j`的元音字母出现次数的奇偶性完全相同。因此,从`i+1`到`j`的区间内,每个元音字母的出现次数必然是偶数次,因为其在这段区间内的出现次数变化抵消了(即奇偶性没有改变)。这是因为任何元音字母的奇数次出现都会改变其对应位的状态,而状态未改变说明出现次数为偶数。
🦆
在实现中,如何处理不在映射`mp`中的非元音字符?
对于不在映射`mp`中的非元音字符,它们不会影响元音字母出现次数的奇偶性跟踪。在题解的算法实现中,当遍历到非元音字符时,位掩码不进行更新,即`st[i+1]`直接继承`st[i]`的值。这样处理保证了位掩码数组只记录和更新元音字母的状态,而忽略非元音字符的干扰。

相关问题