定长字串中元音的最大数目
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
解题思路
本题最简单的思路就是滑动窗口,每次滑动向后滑动一个位置。而每滑动一次,只涉及两个字符的变动,即:
本次滑动新加进来的字符是否是元音
本次滑动去掉的字符是否是元音
示例: 1、假设当前窗口的元音个数是n,那么在滑动时
如果当前窗口的起始位置是元音,那么传递到下一个窗口的元音个数m = n - 1
如果当前窗口的起始位置不是元音,那么传递到下一个窗口的元音个数就是m = n
2、接着,下一个窗口判断新加进来的元素是否是元音。 如果是,则下一个窗口的元音个数就是m + 1,否则为m
3、每个窗口判断当前元音个数tmp是否大于截止当前的最大值result,如果是则result = tmp 4、继续下一个窗口计算
有一个优化点:如果当前窗口的元音个数= k,其实就没必要再继续滑动了,直接return
复杂度分析
时间复杂度:O(n)
只需要最多遍历一遍所有字符
空间复杂度:O(1)
只需要常数空间来存储几个常量
代码
理解了原理,代码就很简单了
普通版:(时间很慢未超时)
class Solution:
def maxVowels(self, s: str, k: int) -> int:
start = maxvowels = _vowels = 0
vowels = {'a', 'e', 'i', 'o', 'u'}
for i, char in enumerate(s):
cursor = s[start: i + 1]
if len(cursor) <= k:
if s[i] in vowels:
_vowels += 1
else:
start += 1
if s[start - 1] in vowels:
_vowels -= 1
if s[i] in vowels:
_vowels += 1
maxvowels = max(_vowels, maxvowels)
return maxvowels
优化版:(时间很快)
class Solution:
def maxVowels(self, s: str, k: int) -> int:
sid, tmp = 0, 0 # 第一个滑动窗口起始位置,当前窗口元音字符个数
fid = k - 1 # 第一个滑动窗口结束位置
mapping = {"a":1, "e":1, "i":1, "o":1, "u":1}
for i in range(fid): # 第一个窗口现在外面判断
if s[i] in mapping:
tmp += 1
result = tmp
while fid < len(s):
if s[fid] in mapping: # 判断窗口往后移动的这个元素是否是元音
tmp += 1 # 如果是元音,则判断当前窗口元音个数与当前结果的大小
result = tmp if tmp > result else result
if tmp >= k: # 如果当前窗口的元音数=k,则直接返回
return k
if s[sid] in mapping: # 判断当前窗口起始位置是否是元音
tmp -= 1 # 将窗口起始位置的元音减去再滑动到下一个窗口
sid += 1 #窗口向后滑动一个元素
fid += 1
return result