最长的指定瑕疵度的元音子串(双指针)
分析思路
题目定义与要求
最长的指定瑕疵度的元音子串问题是一个典型的字符串处理和双指针应用问题。这个问题要求在给定的字符串中找到瑕疵度符合特定要求的最长元音子串,并返回其长度。
具体来说,瑕疵度是指一个元音字符串中非元音字符的数量。
瑕疵度的定义:在这个问题中,瑕疵度指的是元音字符串中非元音字符的数量。
元音字符串的定义:开头和结尾都是元音字母(aeiouAEIOU)的字符串被定义为元音字符串。
子串的定义:子串是指字符串中任意个连续字符组成的子序列。
下面将从多个角度详细解析该问题:
解题方法
- 哈希算法的应用:使用哈希表来确定字符是否为元音,从而快速判断瑕疵度。
- 双指针技术:通过维护一对左指针和右指针来动态调整探索的子串范围,以此寻找满足条件的最长元音子串。
核心思想与逻辑
- 确定瑕疵度:先确定右指针是否指向元音,然后根据瑕疵度的要求调整左指针的位置,直到找到符合条件的最长元音子串。
- 优化操作:选择正确的指针进行优先移动可以节省不必要的操作,提升算法效率。
算法实现细节
-
初始化:将输入字符串转换为小写以简化后续处理,并初始化左右指针及瑕疵度计数器。
迭代过程:遍历字符串,不断更新瑕疵度,并根据当前瑕疵度与预期瑕疵度的比较结果调整左右指针位置。 -
边界情况处理
无满足条件子串:如果找不到满足条件的元音子串,则输出0。
多解情况的处理:如果有多个满足条件的子串,需要记录并更新最长子串的长度。 -
性能考虑
时间复杂度:由于每个字符最多被访问两次(一次是右指针移动,另一次是左指针移动),算法的时间复杂度大致为O(n)。
空间复杂度:除了几个变量以外,没有使用额外的存储空间,因此空间复杂度为O(1)。
进一步分析,还可以从以下几个维度深入探讨:
扩展性考虑:该问题的解决框架可以应用于其他类似的问题,比如寻找具有特定模式的最长子串等。
测试用例的设计:设计全面的测试用例来验证算法的正确性和健壮性是非常重要的,包括各种边界情况和异常情况。
解法
核心思想:先确定右指针是否为元音,否就右移,是就判断瑕疵度是否够且左指针也为元音,都满足才记录,不满足,瑕疵度不够就继续右移右指针,瑕疵度超过就右移左指针,直到瑕疵度小于或等于指定瑕疵度,并进行判断是否记录,最后右移右指针进行下次循环。
function getLongestXiaStr(num, str) {
const yuan = { 'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'A': true, 'E': true, 'I': true, 'O': true, 'U': true };
let res = '';
let l = 0, r = 0, xia = 0;
for (r = 0; r < str.length; r++) {
//利用哈希算法判断右指针是否为元音,即子串结尾要求时元音
if (!yuan[str[r]]) xia++;
//要求足够的瑕疵度
if (!yuan[str[r]] || xia < num) continue;
//足够的瑕疵度,且左边的也是元音,则记录该子串
if (yuan[str[l]] && xia === num) {
let newStr = str.substring(l, r + 1);
newStr.length > res.length ? res = newStr : null;
continue;
}
//当瑕疵度大于要求的瑕疵度或子串左边非元音时,需要移动左指针
while ((!yuan[str[l]] || xia > num) && l < r) {
l++;
if (!yuan[str[l - 1]]) {
xia--;
}
}
//左移动后满足要求
if (yuan[str[l]] && xia === num) {
let newStr = str.substring(l, r + 1);
newStr.length > res.length ? res = newStr : null;
}
}
return res.length;
}
console.log(getLongestXiaStr(2, 'anbgiorioffeiowjiu'))
注意每次如果先判断左指针则每次都要将右指针从头判断到尾,而先判断右指针,左指针只用在原先的基础上移动到下一个符合条件的位置,这样可以节省很多多余的判断。