定长子串中元音的最大数目

标签: 字符串 滑动窗口

难度: Medium

给你字符串 s 和整数 k

请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。

英文中的 元音字母 为(a, e, i, o, u)。

示例 1:

输入:s = "abciiidef", k = 3
输出:3
解释:子字符串 "iii" 包含 3 个元音字母。

示例 2:

输入:s = "aeiou", k = 2
输出:2
解释:任意长度为 2 的子字符串都包含 2 个元音字母。

示例 3:

输入:s = "leetcode", k = 3
输出:2
解释:"lee"、"eet" 和 "ode" 都包含 2 个元音字母。

示例 4:

输入:s = "rhythms", k = 4
输出:0
解释:字符串 s 中不含任何元音字母。

示例 5:

输入:s = "tryhard", k = 4
输出:1

提示:

  • 1 <= s.length <= 10^5
  • s 由小写英文字母组成
  • 1 <= k <= s.length

Submission

运行时间: 70 ms

内存: 16.4 MB

class Solution:
    def maxVowels(self, s: str, k: int) -> int:
        max0=0
        l=len(s)
        for i in s[:k]:
            if i in 'aeiou':
                max0+=1
        nlen=max0
        for ii in range(k,l):
            aa=s[ii-k]
            if aa in 'aeiou':
                nlen-=1
            if s[ii] in 'aeiou':
                nlen+=1
            if nlen>max0:
                max0=nlen
        return max0

Explain

这个题解使用了滑动窗口的方法来解决问题。首先,它计算了字符串s的前k个字符中元音字母的数量,并将其存储在变量max0中。接下来,它遍历从第k个字符到字符串末尾的每个字符。在每次迭代中,它移除窗口最左侧的字符(如果它是元音字母,则从当前计数中减去1),并添加新的右侧字符(如果它是元音字母,则在当前计数中加1)。在每次迭代后,它会检查当前的元音字母计数是否是到目前为止遇到的最大值,并相应地更新max0。最终,max0将包含s中任何长度为k的子字符串可以含有的最大元音字母数量。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def maxVowels(self, s: str, k: int) -> int:
        # 初始化最大元音数为0
        max0 = 0
        l = len(s)
        # 计算第一个窗口中元音的数量
        for i in s[:k]:
            if i in 'aeiou':
                max0 += 1
        # 初始化当前窗口的元音数
        nlen = max0
        # 滑动窗口,从第k个字符开始到结束
        for ii in range(k, l):
            # 移除窗口最左侧的字符
            aa = s[ii-k]
            if aa in 'aeiou':
                nlen -= 1
            # 添加新的右侧字符
            if s[ii] in 'aeiou':
                nlen += 1
            # 更新最大元音字母数
            if nlen > max0:
                max0 = nlen
        return max0

Explore

在算法开始时单独计算初始窗口的元音字母数是为了初始化元音字母的计数基础,从而为滑动窗口提供起始点。直接使用滑动窗口方法需要先有一个基准窗口的元音数,这样在后续滑动时,只需要做增减调整,避免了每次都要重新计算整个窗口的元音字母数,从而提高了效率。

如果字符串s的长度小于k,按照当前算法逻辑,将会在尝试访问不存在的索引时引发错误。为了处理这种情况,可以在函数开始时添加一个检查条件:如果字符串长度小于k,则直接返回0,因为不可能有长度为k的子字符串。

在每次滑动窗口后立即检查并更新最大元音字母数可以确保不遗漏任何可能的最大值。如果推迟到特定点统一更新,可能会错过中间的一些最大值情况。此外,实时更新可以保持算法的简洁性,并实时反映最新的计算结果。

是的,如果字符串s包含大写元音字母,当前的算法将无法正确识别并计数这些元音字母,因此会影响算法的准确性。为了解决这个问题,可以在检查字符是否为元音字母前,先将字符串s转换为全小写,或者在元音字符集中加入大写元音字母('AEIOU')。