青训营X豆包MarsCode - 第三篇| 豆包MarsCode AI 刷题

98 阅读3分钟

青训营X豆包MarsCode - 第三篇滑窗- 41| 豆包MarsCode AI 刷题

氦嗨氦,上两期已经速滑,有中等有困难,今日再挑一道巩固一下,让我们继续嗯滑,应滑尽滑!

今天这题其实也很经典,精髓就在于怎么看出来他是不是要用滑动窗口来开滑。

不说俏皮话了,题号 41 - 最小替换子串长度

题目原文

小F得到了一个特殊的字符串,这个字符串只包含字符ASDF,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得ASDF这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。

题目抽象分析

  • “子串”
  • 约束条件——替换操作使得字符串中的四个特定字符ASDF出现的频次相等
  • 典型的滑动窗口问题

整体思路

为了找到最小的子串,

  • 首先统计每个字符的当前频次,
  • 然后确定每个字符需要增加或减少的频次以达到目标,
  • then,我们使用滑动窗口的方法遍历字符串,调整窗口大小,不断比一比,until找到满足条件的最小子串,

return is fine

代码分块解析

优化一下,把滑窗以外和滑窗以内的部分split开,我们分开列举看看

全局变量部分

  1. 计算目标频次target_freq 为字符串长度除以4,因为每个字符的目标频次应该是相等的。
  2. 统计当前频次:使用字典 current_freq 来记录每个字符在字符串中出现的次数。
  3. 计算需要改变的频次need_change 字典记录了每个字符需要增加或减少的次数。

滑动窗口以内

标准流程了

  1. 初始化窗口leftright 分别表示窗口的左右边界,min_length 记录满足条件的最小子串长度。
  2. 扩展窗口:通过内层循环,将字符添加到窗口中,并更新窗口内的字符频次。
  3. 检查并调整窗口:当窗口内的字符频次满足条件时,尝试缩小窗口以找到更小的子串。

解题步骤

  • 感觉上面写的很通透了,这里就不展开写了。

代码部分

def solution(input):
    n = len(input)
    target_freq = n // 4  # 目标频次
    
    # 统计当前频次
    current_freq = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
    for char in input:
        current_freq[char] += 1
    
    # 计算每个字符需要增加或减少的次数
    need_change = {char: max(0, current_freq[char] - target_freq) for char in 'ASDF'}
    
    # 如果所有字符的频次已经相等,直接返回0
    if sum(need_change.values()) == 0:
        return 0
    
    # 使用滑动窗口找到最小的子串
    left = 0
    min_length = n  # 初始化为最大可能值
    window_count = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
    
    for right in range(n):
        window_count[input[right]] += 1
        
        # 检查当前窗口是否满足替换条件
        while all(window_count[char] >= need_change[char] for char in 'ASDF'):
            min_length = min(min_length, right - left + 1)
            window_count[input[left]] -= 1
            left += 1
    
    return min_length
​
if __name__ == "__main__":
    #  You can add more test cases here
    print(solution("ADDF") == 1)
    print(solution("ASAFASAFADDD") == 3)

复杂度分析

  • 时间复杂度:O(n),其中 n 是字符串的长度。尽管有两层循环,但每个字符只被遍历一次。
  • 空间复杂度:O(1),使用的额外空间与字符串长度无关,只存储了固定数量的字符频次。

总结

在实际这种刷题里面,滑动窗口技术常用于解决类似的最优子串问题,看到“子串”“子区间”这种连续seq就得要下意识反应了。

滑窗自此估计要告一段落,下个专题再考虑一下还做刷题or其他deep talk一点的,预告禁止(bushi

下次再say啦~