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

38 阅读3分钟

题目分析

题目要求我们通过尽可能少的替换,使得给定字符串中的字符 A、S、D、F 出现的频次相等。字符串的长度总是 4 的倍数,因此每个字符的目标频次是字符串长度的四分之一。

我们需要找到一个最短的子串,通过替换该子串中的某些字符,使得整个字符串满足每个字符的频次相等。

解题思路

所以解题思路就比较清晰了,用滑动窗口做字符串替换。

  1. 统计字符频次:首先统计字符串中每个字符的出现频次。
  2. 确定需要替换的字符:找出哪些字符的频次超过目标频次,并计算需要替换的数量。
  3. 滑动窗口:使用滑动窗口技术找到包含所有需要替换字符的最小子串。

代码实现

def solution(input_str):
    n = len(input_str)
    count_target = n // 4

    # 统计每个字符的频率
    frequency = {}
    for c in input_str:
        if c in frequency:
            frequency[c] += 1
        else:
            frequency[c] = 1

    # 找出需要替换的字符以及需要替换的数量
    required_changes = {}
    for ch, count in frequency.items():
        if count > count_target:
            required_changes[ch] = count - count_target

    # 如果不需要替换,直接返回 0
    if not required_changes:
        return 0

    # 使用滑动窗口找到最小的子串
    left, right = 0, 0
    min_len = n + 1
    window_count = {}

    while right < n:
        right_char = input_str[right]
        if right_char in window_count:
            window_count[right_char] += 1
        else:
            window_count[right_char] = 1
        right += 1

        # 检查当前窗口是否包含所有需要替换的字符
        def window_contains_required_changes():
            for ch, req_count in required_changes.items():
                if window_count.get(ch, 0) < req_count:
                    return False
            return True

        while window_contains_required_changes():
            min_len = min(min_len, right - left)
            left_char = input_str[left]
            if left_char in window_count:
                window_count[left_char] -= 1
            left += 1

    return min_len

if __name__ == "__main__":
    import sys

    input_str = input().strip()
    print(solution(input_str))

代码解释

  1. 统计字符频次

    • count_target = n // 4 计算每个字符的目标频次。
    • frequency 字典统计字符串中每个字符的出现频次。
  2. 确定需要替换的字符

    • required_changes 字典记录需要替换的字符及其超过目标频次的数量。
    • 如果 required_changes 为空,说明字符串已经满足条件,直接返回 0。
  3. 滑动窗口

    • 初始化两个指针 leftright,用于表示滑动窗口的左右边界。
    • min_len 用于记录最小子串的长度,初始值设为 n + 1,表示一个不可能的值。
    • window_count 字典用于记录当前窗口中每个字符的频次。
    • while right < n 循环中,右指针 right 逐渐向右移动,扩展窗口。
    • window_contains_required_changes 函数检查当前窗口是否包含所有需要替换的字符及其数量。
    • 如果当前窗口包含所有需要替换的字符,则左指针 left 逐渐向右移动,缩小窗口,同时更新 min_len

测试样例

  • 样例1:输入 "ADDF",输出 1。
    • 字符频次:A(1), D(2), F(1)。
    • 需要替换 D 一次。
    • 最小子串长度为 1。
  • 样例2:输入 "ASAFASAFADDD",输出 3。
    • 字符频次:A(4), S(2), F(2), D(4)。
    • 需要替换 D 一次。
    • 最小子串长度为 3。
  • 样例3:输入 "SSDDFFFFAAAS",输出 1。
    • 字符频次:S(3), D(2), F(4), A(3)。
    • 需要替换 F 一次。
    • 最小子串长度为 1。
  • 样例4:输入 "AAAASSSSDDDDFFFF",输出 0。
    • 字符频次:A(4), S(4), D(4), F(4)。
    • 已经满足条件,不需要替换。
  • 样例5:输入 "AAAADDDDAAAASSSS",输出 4。
    • 字符频次:A(6), D(4), S(4)。
    • 需要替换 A 两次。
    • 最小子串长度为 4。