字符串计数匹配 - 华为OD机试真题(Python题解)

华为OD机试题库《C++》限时优惠 9.9

华为OD机试题库《Python》限时优惠 9.9

华为OD机试题库《JavaScript》限时优惠 9.9

针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)。

看不懂有疑问需要答疑辅导欢迎私VX: code5bug

华为OD机试真题

题目描述

给你一个字符串 str和整数k,返回满足以下条件的所有子字符串个数:

  1. 恰好包含k 个字母
  2. 数字0-9各出现至少一次

输入描述

第一行为字符串 str (1 <= length <= 100000),仅包含数字和小写字母。

第二行为整数k(0 <= k <= 100000)

输出描述

输出一个整数,表示满足条件的所有子字符串个数

补充说明

子字符串 是字符串中连续的 非空 字符序列

示例1

输入:

a0123456789aa
1

输出:

2

示例2

输入:

aa01234a5678901234aa
1

输出:

22

题解

  1. 滑动窗口法:使用两个滑动窗口来维护满足条件的子字符串。
    1. 窗口1(left1):指向满足恰好k个字母且所有数字0-9都出现至少一次的最早左边界。
    2. 窗口2(left2):指向不满足恰好k个字母且所有数字0-9都出现至少一次的最早左边界。
  2. 双指针维护:使用两个指针left1left2来分别维护窗口1和窗口2的左边界。
  3. 统计数字频率:使用哈希表(或字典)来统计当前窗口中数字的出现频率,确保所有数字0-9都至少出现一次。
  4. 计算有效子字符串:对于每个右指针right,计算满足条件的子字符串的左指针范围[left1, left2),并将该范围内的子字符串数量累加到结果中。

Python

"""
@author: code5bug
"""
from collections import defaultdict

s = input()
k = int(input())

# 两个窗口中的字符个数计数和对应的左指针
letter_count1 = left1 = 0
letter_count2 = left2 = 0
# 对两个窗口出现的数字进行计数统计
digit_freq1, digit_freq2 = defaultdict(int), defaultdict(int)

# 满足要求的子串个数
ans = 0
for right, c in enumerate(s):
    if c.isalpha():
        letter_count1 += 1
        letter_count2 += 1
    else:
        digit_freq1[c] += 1
        digit_freq2[c] += 1

    # 窗口形成的子串不满足要求则继续扩大窗口
    if letter_count2 < k or len(digit_freq2) < 10:
        continue

    # 为了形成 [left1, left2) ~ right 的子串都是满足要求的子字符串
    # 所以 left2 为最早不满足要求的位置
    while letter_count2 >= k and len(digit_freq2) == 10:
        left_char = s[left2]
        left2 += 1
        if left_char.isalpha():
            letter_count2 -= 1
        else:
            if digit_freq2[left_char] == 1:
                del digit_freq2[left_char]
            else:
                digit_freq2[left_char] -= 1

    # left1 为满足要求的最早的位置
    while letter_count1 > k:
        left_char = s[left1]
        left1 += 1
        if left_char.isalpha():
            letter_count1 -= 1
        else:
            if digit_freq1[left_char] == 1:
                del digit_freq1[left_char]
            else:
                digit_freq1[left_char] -= 1

    # left1 和 left2 之间的区间就是满足题目要求子串的左指针有效取值范围
    ans += left2 - left1

print(ans)

希望这个专栏能让您熟练掌握算法, 🎁🎁🎁。

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什码情况

你的鼓励就是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值