• 【限时免费】20天拿下华为OD笔试之【不定滑窗】2023Q1A-完美走位【欧弟算法】全网注释最详细分类最全的华为OD真题题解


    【不定滑窗】2023Q1A-完美走位

    题目描述与示例

    题目

    在第一人称射击游戏中,玩家通过键盘的 ASDW 四个按键控制游戏人物分别向左、向后、向右、向前进行移动,从而完成走位。

    假设玩家每按动一次键盘,游戏人物会向某个方向移动一步,如果玩家在操作一定次数的键盘并且各个方向的步数相同时,此时游戏人物必定会回到原点,则称此次走位为完美走位

    现给定玩家的走位(例如:ASDA),请通过更换其中一段连续走位的方式使得原走位能够变成一个完美走位。 其中待更换的连续走位可以是相同长度的任何走位。

    请返回待更换的连续走位的最小可能长度。若果原走位本身是一个完美走位,则返回 0

    输入

    输入为由键盘字母表示的走位s,例如:ASDA

    输出

    输出为待更换的连续走位的最小可能长度

    备注

    1. 走位长度 1 ≤ s.length ≤ 10^5
    2. s.length4 的倍数
    3. s 中只含有 A, S, D, W 四种字符

    示例一

    输入

    ASDW
    
    • 1

    输出

    0
    
    • 1

    说明

    已经是完美走位了。

    示例二

    输入

    AASW
    
    • 1

    输出

    1
    
    • 1

    说明

    需要把一个 A 更换成 D,这样可以得到 ADSW 或者 DASW

    示例三

    输入

    AAAA
    
    • 1

    输出

    3
    
    • 1

    说明

    可以替换后 3A,得到 ASDW

    示例四

    输入

    AAAAADDD
    
    • 1

    输出

    4
    
    • 1

    解题思路

    注意,本题和LC76. 最小覆盖子串几乎完全一致。重点在于如何将原问题转化为覆盖子串的问题。

    题目有两个重要条件:

    1. 完美走位字符串是指字符串中ASDW四种字符出现次数相等的字符串
    2. s.length4 的倍数

    对于长度为len(s)的原字符串s来说,为了使其转变为一个完美走位字符串,其中ASDW四种字符出现次数应该均为 num = len(s) // 4

    原字符串s中各个字符出现的次数可以用哈希表cnt_s = Counter(s)进行统计,对于出现次数多于num = len(s) // 4的字符ch,应该修改 cnt_s[ch] - len(s) // 4 个字符为其他出现次数少于num = len(s) // 4的字符,才能够使得s变为一个完美走位字符串。

    以示例四为例,s = "AAAAADDD",字符"A"出现的次数为5,字符"D"应该修改3,而num = len(s) // 4 = 2,需要修改3"A"1"D"为剩余两种字符,才能使得s变为完美走位字符串。故我们需要找到包含3"A"1"D"的最小子串。

    因此这个问题就转变为了,找到覆盖cnt_s[ch] - len(s) // 4个的字符chch满足条件cnt_s[ch] > len(s) // 4)的最短子串。需要覆盖的子串中所出现的字符以及次数,可以用另一个哈希表cnt_sub储存。

    那么这个问题就和LC76. 最小覆盖子串完全一致了,直接滑窗三问三答解决即可。上述逻辑整理为代码即

    num = len(s) // 4
    cnt_s = Counter(s)
    cnt_sub = {k: v-num for k, v in cnt_s.items() if v > num}
    
    • 1
    • 2
    • 3

    代码

    # 题目:2023Q1A-完美走位
    # 分值:200
    # 作者:许老师-闭着眼睛学数理化
    # 算法:不定滑窗
    # 代码看不懂的地方,请直接在群上提问
    
    
    from collections import Counter
    from math import inf
    
    
    # 定义辅助函数check()
    # 用于检查cnt_sub中的各个字符是否出现在cnt_win中,
    # 且cnt_win中的个数大于等于cnt_sub
    def check(cnt_win, cnt_sub):
        return all(cnt_win[k] >= cnt_sub[k] for k in cnt_sub)
    
    
    s = input()
    num = len(s) // 4
    # 获得原字符串中所有字符的出现次数
    cnt_s = Counter(s)
    # 获得需要覆盖的子串的字符以及出现次数
    cnt_sub = {k: v-num for k, v in cnt_s.items() if v > num}
    
    # 如果cnt_sub长度为0,说明每一种字符出现次数相等
    # s已经是一个完美走位字符串,输出0
    if len(cnt_sub) == 0:
        print(0)
    # 否则要进行类似LC76. 最小覆盖子串的不定滑窗过程
    else:
        # 初始化滑窗对应的哈希表、最小覆盖的窗口长度
        cnt_win = Counter()
        ans = inf
        left = 0
    
        for right, ch in enumerate(s):
            # Q1:对于每一个右指针right所指的元素ch,做什么操作?
            # A1:将其加入哈希表cnt_win的计数中
            cnt_win[ch] += 1
            # Q2:什么时候要令左指针left右移?在什么条件下left停止右移?【循环不变量】
            # A2:check(cnt_win, cnt_sub)为True,left可以右移以缩小窗口长度
            while check(cnt_win, cnt_sub):
                # Q3:什么时候进行ans的更新?
                # A3:check(cnt_win, cnt_sub)为True
                ans = min(ans, right-left+1)
                cnt_win[s[left]] -= 1
                left += 1
    
        print(ans)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    时空复杂度

    时间复杂度:O(N)。仅需一次遍历整个字符串s

    空间复杂度:O(1)。只有4种字符,哈希表所占用空间为常数级别空间。


    华为OD算法/大厂面试高频题算法练习冲刺训练

    • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

    • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

    • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

    • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

    • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

    • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

    • 绿色聊天软件戳 od1336了解更多

  • 相关阅读:
    Linux: IO中断驱动开发教程
    如何通过VNC实现公网远程控制macOS设备
    LSTM 词语模型上的动态量化
    接口自动化测试:mock server之Moco工具
    【C++】运算符重载 ② ( 类内部定义云算符重载 - 成员函数 | 类外部定义运算符重载 - 全局函数 | 可重载的运算符 )
    正点原子IMX6ULL驱动开发复盘
    【React】第六部分 生命周期
    最多免费玩30分钟,“先试后买”会是Quest商店的救星吗?
    基于反馈技术的宽带低噪声放大器的设计
    MobaXterm使用VNC远程显示和控制ubuntu桌面
  • 原文地址:https://blog.csdn.net/weixin_48157259/article/details/131767997