目录
题目
最长的指定瑕疵度的元音子串
题目描述
解答要求
答案
解析
核心思想
注意要选好先判断左指针还是右指针可以节省不必要的操作。
hash算法、双指针
定义:开头和结尾都是元音字母(aeiouAEIOU)的字符串为元音字符串,其中混杂的非元音字母数量为瑕疵度。比如:
“a”、“aa”是元音字符串,其瑕疵度都为0
“aiur”不是元音字符串(结尾不是元音字符)
“abira”是元音字符串,其瑕疵度为2
给定一个字符串,请找出指定瑕疵度的最长元音字符子串,并输出其长度,如果找不到满足条件的元音字符子串,输出0.
子串:字符串中任意个连续的字符组成的子序列称为该字符串的子串
时间限制:1000ms,内存限制:256MB
输入
首行输入是一个整数,表示预期的瑕疵度flaw,取值范围[0,65535]。
接下来一行是一个仅由字符a-z和A-Z组成的字符串,字符串长度(0,65535]。
输出
输出为一个整数,代表满足条件的元音字符子串的长度。
样例
输入样例1
0
asdbuiodevauufgh
输出样例1
3
提示样例1
满足条件的最长元音字符子串有两个,分别为uio和auu,长度为3。
输入样例2
2
aeueo
输出样例2
0
提示样例2
没有满足条件的元音字符子串,输出0.
输入样例3
1
aabeebuu
输出样例3
5
提示样例3
满足条件的最长元音字符子串有两个,分别为aabee和eebuu,长度为5
const getLongestFlawedVowelSubstrLen = (flaw, input) => { input = input.toLowerCase() //利用hash算法确定是否为元音 let au = { a: 1, e: 1, i: 1, o: 1, u: 1 } let left = 0 let right = 0 let arr = [] let count = 0 //每次循环右指针向右进一格,直到遍历完数组 for (right = 0; right < input.length; right++) { //利用哈希算法判断右指针是否为元音,即子串结尾要求时元音 let isRightYuan = au[input[right]] === 1 ? true : false if (isRightYuan === false) { count++ } //要求足够的瑕疵度 if (isRightYuan === false || count < flaw) { continue } //足够的瑕疵度,且左边的也是元音,则记录该子串 if (count === flaw && au[input[left]] === 1) { let temp = input.substring(left, right + 1) arr.push(temp) continue } //当瑕疵度大于要求的瑕疵度或子串左边非元音时,需要移动左指针 while (count > flaw || au[input[left]] !== 1) { left++ if (au[input[left - 1]] !== 1) { count-- } if (left > right) { left = right break } } //记录跳出循环时是否符合要求 if (count == flaw && au[input[left]] === 1) { let temp = input.substring(left, right + 1) arr.push(temp) } } if (arr.length > 1) { //按长度大小给子串排序 arr.sort((a, b) => b.length - a.length) if (arr.length > 0) { return arr[0].length } } else if (arr.length === 1) { return arr[0].length } else { return 0 } } console.log(getLongestFlawedVowelSubstrLen(0, 'asdbuiodevauufgh'))
注意每次如果先判断左指针则每次都要将右指针从头判断到尾,而先判断右指针,左指针只用在原先的基础上移动到下一个符合条件的位置,这样可以节省很多多余的判断。
先确定右指针是否为元音,否就右移,是就判断瑕疵度是否够且左指针也为元音,都满足才记录,不满足,瑕疵度不够就继续右移右指针,瑕疵度超过就右移左指针,直到瑕疵度小于或等于指定瑕疵度,并进行判断是否记录,最后右移右指针进行下次循环。