青训营X豆包MarsCode AI刷题-3 | 豆包MarsCode AI 刷题

31 阅读2分钟

问题描述

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

关键点

  1. 字符频次相等

    • 字符串长度为4的倍数,因此每个字符的目标频次为 n // 4,其中 n 是字符串的长度。
  2. 最小子串长度

    • 需要找到一个最小的子串,使得通过替换该子串中的字符,可以使整个字符串的A、S、D、F频次相等。
  3. 滑动窗口

    • 使用滑动窗口技术来找到满足条件的最小子串。

解决方案

我们可以通过以下步骤来解决这个问题:

  1. 计算目标频次

    • 计算每个字符的目标频次 target_freq = n // 4
  2. 计算整个字符串的字符频次

    • 遍历字符串,计算每个字符的频次,存储在 total_count 字典中。
  3. 检查是否已经满足条件

    • 如果所有字符的频次已经等于目标频次,直接返回0。
  4. 滑动窗口

    • 使用滑动窗口技术来找到满足条件的最小子串。
    • 初始化窗口的左边界 left 和右边界 right
    • 扩展右边界 right,更新窗口内字符的频次 window_count
    • 检查当前窗口是否可以满足条件(即窗口外的字符频次不超过目标频次)。
    • 如果满足条件,更新最小子串长度,并尝试缩小左边界 left
  5. 返回结果

    • 返回找到的最小子串长度。

代码实现

def solution(input):
    n = len(input)
    target_freq = n // 4
    
    # 计算整个字符串中每个字符的频次
    total_count = {'A': 0, 'S': 0, 'D': 0, 'F': 0}
    for char in input:
        total_count[char] += 1
    
    # 如果已经满足条件,直接返回0
    if all(total_count[char] == target_freq for char in 'ASDF'):
        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 left <= right and all(total_count[char] - window_count[char] <= target_freq for char in 'ASDF'):
            min_length = min(min_length, right - left + 1)
            window_count[input[left]] -= 1
            left += 1
    
    return min_length

# 测试样例
print(solution("ADDF"))  # 输出:1
print(solution("ASAFASAFADD0"))  # 输出:3
print(solution("SSDDFFFFAAAS"))  # 输出:1
print(solution("AAAASSSSDDDDFFFF"))  # 输出:0
print(solution("AAAADDDAAAASSSS"))  # 输出:4

总结

通过使用滑动窗口技术,我们可以高效地找到满足条件的最小子串长度。每次扩展右边界并更新窗口内字符的频次,检查当前窗口是否可以满足条件,并尝试缩小左边界以找到更小的子串。最终得到的 min_length 即为满足条件的最小子串长度。