最小替换子串长度 | 豆包MarsCode AI刷题

52 阅读4分钟

问题解析

问题目标

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

测试样例

样例1:

输入:input = "ADDF"
输出:1

样例2:

输入:input = "ASAFASAFADDD"
输出:3

样例3:

输入:input = "SSDDFFFFAAAS"
输出:1

样例4:

输入:input = "AAAASSSSDDDDFFFF"
输出:0

样例5:

输入:input = "AAAADDDDAAAASSSS"
输出:4


问题解析

  1. 频次平衡目标

    • 字符串长度为 nnn,所以每个字符(A、S、D、F)的目标频次为 target=n/4\text{target} = n / 4target=n/4。
  2. 滑动窗口方法

    • 使用滑动窗口确定一个子串,当替换这个子串内的字符后,剩余的字符能满足目标条件。
    • 通过调整窗口的左右边界(leftright),动态计算窗口内字符对整体字符频次的影响。
  3. 判断条件

    • 每次调整窗口后,判断去除窗口内的字符后,剩余字符的频次是否都小于等于目标频次。

实现思路

  1. 初始化

    • 使用 Counter 统计字符串中每个字符的频次。
    • 如果字符频次已满足平衡条件(即每个字符的频次等于 target),返回0。
  2. 滑动窗口操作

    • 窗口移动

      • right 向右扩展窗口。
      • 在每次扩展窗口后,更新 count,使窗口内的字符频次减少。
    • 窗口收缩

      • 检查当前窗口外的字符是否满足平衡条件(每个字符的频次 ≤ target)。
      • 如果满足,更新最小子串长度,尝试移动 left 来收缩窗口。
  3. 返回结果


代码实现

from collections import Counter

def solution(input):

    n = len(input)
    target = n // 4  # 每个字符的目标频次
    count = Counter(input)  # 统计字符频次
    
    # 如果当前字符串已经平衡,直接返回0
    if all(count[c] == target for c in "ASDF"):
        return 0
    
    min_len = n  # 初始化最小子串长度为字符串长度
    left = 0
    
    # 右边界遍历字符串
    for right in range(n):
    
        count[input[right]] -= 1  # 窗口内右边界字符频次减1
        
        # 窗口内外频次检查:窗口外的字符频次都 <= target
        while all(count[c] <= target for c in "ASDF"):
            min_len = min(min_len, right - left + 1)  # 更新最小子串长度
            count[input[left]] += 1  # 窗口内左边界字符频次恢复
            left += 1  # 收缩窗口
        
    return min_len

时间复杂度:

  • 主要循环:
    外层循环 for right in range(n) 遍历了整个字符串,每个字符最多被访问两次(一次通过 right,一次通过 left)。

  • 内部循环:
    内部的 while 循环在滑动窗口内收缩,最多也是 O(n) 次。因此,总的时间复杂度为 O(n)

  • 综合时间复杂度:

O(n)+O(n)×O(1)=O(n)

空间复杂度:

  • Counter 对象:
    Counter 使用了一个字典来存储字符频次。对于仅包含 A、S、D、F 的固定字符集,最多存储4个键值对。所以,空间复杂度是 O(1)

知识总结

  1. 频率统计:

    • 统计字符串中目标字符的频率。
    • 确定每个字符的理想频率,即 target = len(s) / 4
  2. 滑动窗口:

    • 使用滑动窗口高效地遍历字符串的所有可能子串。
    • 调整窗口左右边界,动态找到满足条件的最小窗口。
  3. 窗口调整逻辑:

    • 右扩: 确保窗口内覆盖到足够的字符。
    • 左缩: 找到更小的满足条件的窗口,从而优化结果。

学习计划

  • 每天设定固定的刷题数量,分级学习,逐渐掌握不同类型的题目,通过豆包AI题目记录,对错题解析,巩固易错点。通过题目解析,利用豆包AI的刷题功能,不断深挖算法,理解并去记忆其思路。

工具运用

  1. 结合豆包 AI 提供的解析,与在线教程进行交叉验证,巩固理解。利用算法书补充理论知识。

  2. 参与稀土掘金社区讨论,分享 AI 提供的解决方案和优化思路。