Leetcode3305:元音辅音字符串计数 I

题目描述:

给你一个字符串 word 和一个 非负 整数 k

返回 word 的 子字符串 中,每个元音字母('a''e''i''o''u'至少 出现一次,并且 恰好 包含 k 个辅音字母的子字符串的总数。

代码思路:

主函数逻辑

  • 计算 f(k) 和 f(k+1) 的差值,这样可以得到恰好包含至少 k 个辅音字母的子字符串数量。
  • f(k) 计算的是包含至少 k 个辅音字母的子字符串数量,而 f(k+1) 计算的是包含至少 k+1 个辅音字母的子字符串数量。
  • 它们的差即为包含恰好 k 个辅音字母的子字符串数量。

函数 f(k) 的作用

  1. 输入与初始化:
    • 输入是字符串 word 和整数 k
    • 计算字符串的长度 n
    • 使用一个计数器 cnter 来记录当前子字符串中各个字符的出现次数。
    • 初始化指针 j 为 0,用于表示当前子字符串的起始位置。
    • 初始化结果变量 ans 为 0,用于累计满足条件的子字符串数量。
  2. 滑动窗口遍历字符串:
    • 使用 for 循环和指针 i 从头到尾遍历字符串 word
    • 对每个字符 w,在计数器 cnter 中增加其计数。
  3. 检查并调整窗口:
    • 在每次移动 i 后,检查当前窗口 [j, i] 是否满足条件:包含所有五个元音字母,且辅音字母数量不少于 k
    • 条件检查:
      • cnter['a']cnter['e']cnter['i']cnter['o']cnter['u'] 都大于 0。
      • 窗口内的辅音数量 i - j + 1 - (cnter['a'] + cnter['e'] + cnter['i'] + cnter['o'] + cnter['u']) 大于等于 k
    • 如果满足条件,移动 j 指针以缩小窗口,直到不再满足条件为止:
      • 减少 word[j] 在 cnter 中的计数。
      • 增加 j
  4. 累计结果:
    • 每次调整完窗口后,将 j 加到 ans 中。这里 j 表示以当前 i 为结尾的满足条件的子字符串的数量。
  5. 返回结果:
    • 函数 f(k) 返回满足条件的子字符串总数。

 代码实现:

class Solution:
    def countOfSubstrings(self, word: str, k: int) -> int:
        n = len(word)
        def f(k): # 表示每个元音至少出现一次且辅音至少出现k次的子字符串总数
            ans = 0
            cnter = Counter()
            j=0 # [i,j] 表示此时刚好不满足要求的子字符串下标区间
            for i,w in enumerate(word):
                cnter[w] += 1
                while cnter['a'] and cnter['e'] and cnter['i'] and cnter['o'] and cnter['u'] and \
                    i-j+1-(cnter['a']+cnter['e']+cnter['i']+cnter['o']+cnter['u'])>=k:
                    cnter[word[j]] -= 1
                    j += 1
                ans += j # 表示 word[0~i]与word[j-1~i]都满足条件,将他们都记录到答案中,一共有j个
            return ans
        return f(k)-f(k+1)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值