最小替换字符串 | 豆包MarsCode AI刷题

51 阅读4分钟

题目解析

题目

通过最少替换字符,使得字符串中四种字符(A、S、D、F)的出现频次相等,求最小需要替换的子串长度。

测试样例

样例1:

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

样例2:

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

样例3:

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

样例4:

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

样例5:

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

思路解析

  1. 问题拆解

    • 如果字符数量完全均匀,则无需替换,直接返回 0;否则,需要通过调整子串来让字符频次均匀。
    • 对于一个长度为 nn 的字符串,理想状态下每个字符应出现 n/4n/4 次。
  2. 滑动窗口法

    • 计算每个字符的实际出现次数,找出需要调整的字符及其超出的数量。
    • 使用滑动窗口尝试覆盖这些超出部分,滑动窗口中的字符正好可以替换成缺失的字符。
    • 窗口滑动的过程中动态维护最小覆盖长度。
  3. 实现步骤

    • 统计字符频次。
    • 判断是否需要调整,若四个字符均不超标,直接返回 0。
    • 初始化滑动窗口,尝试找到满足条件的最小子串。

图解

  1. 统计字符频次

    A: 5, S: 4, D: 6, F: 3 (总长度=18)
    理想频次=18/4=4
    超出部分: A=1, D=2, F=-1 (F未超出)
    
  2. 滑动窗口覆盖超出部分

    • 起始窗口范围 [0, 0],窗口内字符计数。
    • 窗口扩展至 [0, 5],尝试覆盖超出的频次。
    • 动态更新最小窗口长度。

代码详解

from collections import Counter

def min_window_to_balance(input_string):
    n = len(input_string)
    ideal_count = n // 4
    
    # 统计字符频次
    freq = Counter(input_string)
    
    # 记录需要减少的字符及其数量
    excess = {char: max(0, freq[char] - ideal_count) for char in 'ASDF'}
    if sum(excess.values()) == 0:
        return 0

    # 滑动窗口寻找最小覆盖子串
    left = 0
    min_length = n
    
    for right in range(n):
        excess[input_string[right]] -= 1
        
        # 如果窗口当前已满足条件,尝试收缩
        while all(excess[char] <= 0 for char in 'ASDF'):
            min_length = min(min_length, right - left + 1)
            excess[input_string[left]] += 1
            left += 1

    return min_length

# 测试用例
print(min_window_to_balance("ADDF"))         # 输出:1
print(min_window_to_balance("ASAFASAFADDD")) # 输出:3
print(min_window_to_balance("SSDDFFFFAAAS")) # 输出:1
print(min_window_to_balance("AAAASSSSDDDDFFFF")) # 输出:0
print(min_window_to_balance("AAAADDDDAAAASSSS")) # 输出:4

知识总结

新知识点
  1. 滑动窗口法

    • 滑动窗口是一种高效解决子数组问题的技巧,可以动态调整窗口范围,减少不必要的计算。
  2. Counter类的应用

    • collections.Counter 是统计字符频次的高效工具,能够快速初始化、更新和查询。
  3. 动态维护条件

    • 利用字典记录字符频次,动态判断是否满足条件,提高了算法效率。
学习建议
  • 滑动窗口对于解决涉及子串或子数组的问题非常重要,建议入门者多练习类似问题。
  • 学会结合实际问题选择适当的数据结构(如字典、队列),以提升代码可读性和效率。

学习计划

  1. 制定刷题计划

    • 每周选择一类问题(如滑动窗口、动态规划、二分查找等),每天练习 3 道相关题目。
    • 对错题归类,分析错误原因并整理成错题本。
  2. 利用错题进行针对性学习

    • 将错题分为概念性错误和细节性错误。
    • 概念性错误:补充相关知识点,重新学习。
    • 细节性错误:注重代码实现和调试能力。
  3. 结合复习和实践

    • 定期复习错题本,回顾解题思路。
    • 利用MarsCode AI的题目推荐功能,针对弱项进行专项突破。

工具运用

  1. MarsCode AI 刷题功能

    • 使用题目分类功能精准定位需要练习的题型。
    • 利用代码分析功能,检查代码风格并优化性能。
  2. 结合其他学习资源

    • 将MarsCode AI的练习题与LeetCode、牛客等平台题目对照练习。
    • 使用Markdown记录学习心得,便于回顾和分享。
  3. 社区交流

    • 在论坛或社区中分享自己的刷题经验,获取他人建议,提升解决问题的多样性。