Copy 给你一个字符串 s ,请你返回满足以下条件的最长子字符串的长度:每个元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出现了偶数次。
示例 1:
输入:s = "eleetminicoworoep"
输出:13
解释:最长子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 个,以及 0 个 a,u 。
示例 2:
输入:s = "leetcodeisgreat"
输出:5
解释:最长子字符串是 "leetc" ,其中包含 2 个 e 。
示例 3:
输入:s = "bcbcbc"
输出:6
解释:这个示例中,字符串 "bcbcbc" 本身就是最长的,因为所有的元音 a,e,i,o,u 都出现了 0 次。
提示:
1 <= s.length <= 5 x 10^5
s 只包含小写英文字母。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-longest-substring-containing-vowels-in-even-counts
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
Copy /**
* @param {string} s
* @return {number}
*/
var findTheLongestSubstring = function (s) {
for (let subStrLen = s.length; subStrLen >= 0; subStrLen--) {
let remove = s.length - subStrLen + 1;
for (let start = 0; start < remove; start++) {
let subStr = s.slice(start, start + subStrLen);
if (hasEvenVowels(subStr)) return subStrLen;
}
}
// *********************************
function hasEvenVowels(s) {
const vowels = ['a', 'e', 'i', 'o', 'u'];
return !vowels.some(
v => (s.match(new RegExp(v, 'g')) || []).length % 2 !== 0,
);
}
};
Copy /**
* @param {string} s
* @return {number}
*/
var findTheLongestSubstring = function (s) {
const vowels = {
a: 0,
e: 1,
i: 2,
o: 3,
u: 4,
};
// 前缀和数组
const prefix = Array(s.length)
.fill(0)
.map(() => Array(5).fill(0));
for (let i = 0; i < s.length; i++) {
const c = s[i];
// 计算 [0, i] 区间每个元音出现的次数
// 我就直接调 API 复制上一个数组了 ╮(╯▽╰)╭
if (prefix[i - 1]) prefix[i] = prefix[i - 1].slice(0);
if (c in vowels) prefix[i][vowels[c]]++;
}
// 枚举子串,i 是子串长度
// 先从最长的子串开始枚举,是一个剪枝小技巧
for (let i = s.length - 1; i >= 0; i--) {
// j 是子串开头,i+j 是子串结束
for (let j = 0; j < s.length - i; j++) {
// 检查子串中元音出现次数,如果有满足条件的,直接返回
if (check(s, prefix, j, i + j)) return i + 1;
}
}
return 0;
// ********************************
function check(s, prefix, l, r) {
for (let i = 0; i < 5; i++) {
// 左边界 - 右边界
let cnt = prefix[r][i] - prefix[l][i];
// 把减掉的左边界再加上
cnt += vowels[s[l]] === i ? 1 : 0;
if (cnt % 2 !== 0) return false;
}
return true;
}
};
Copy /**
* @param {string} s
* @return {number}
*/
var findTheLongestSubstring = function (s) {
const vowels = {
a: 0,
e: 1,
i: 2,
o: 3,
u: 4,
};
const seen = {
0: -1,
};
let status = 0,
ans = 0;
for (let i = 0; i < s.length; i++) {
if (s[i] in vowels) status ^= 1 << vowels[s[i]];
// 如果相同的奇偶性出现过,更新 ans
if (status in seen) {
ans = Math.max(ans, i - seen[status]);
}
// 否则记录当前下标
else {
seen[status] = i;
}
}
return ans;
};