目录
题目
最长的指定瑕疵度的元音子串
题目描述
解答要求
答案
解析
核心思想
注意要选好先判断左指针还是右指针可以节省不必要的操作。
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'))
注意每次如果先判断左指针则每次都要将右指针从头判断到尾,而先判断右指针,左指针只用在原先的基础上移动到下一个符合条件的位置,这样可以节省很多多余的判断。
先确定右指针是否为元音,否就右移,是就判断瑕疵度是否够且左指针也为元音,都满足才记录,不满足,瑕疵度不够就继续右移右指针,瑕疵度超过就右移左指针,直到瑕疵度小于或等于指定瑕疵度,并进行判断是否记录,最后右移右指针进行下次循环。