打卡第一天 | 豆包MarsCode AI刷题

87 阅读3分钟

最小替换子串长度

题目描述

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

解题思路

首先读完题,由于字符串长度是固定为4的倍数,而且字符串中的内容也已经确定了,所以我的第一想法是用哈希表存储四个字符的个数,然后每个字符的字符数减去平均字符数(即string.length / 4)算出需要替换的字符数,但是想到这里我的思绪便停滞了,我们应该如何保证最小替换次数呢,想了一会无果后便向豆包求助, 豆包为我提供了滑动窗口的思路来维护最小子串

image.png

经过豆包的提示之后,成功解出此题。

image.png

代码讲解

哈希表存储可以用python中的字典推导式解决,然后求解需要替换数的总和,先特判,若为零,则直接返回答案,类似于一种剪枝操作,若不为零,则说明有需要替换的字符操作,此时进入滑动窗口阶段

滑动窗口代码详解

  1. 滑动窗口初始化

    left = 0
    min_length = len(input)
    window_counts = {char: 0 for char in 'ASDF'}
    
    • left 表示滑动窗口的左边界,初始值为0。
    • min_length 初始化为输入字符串的长度,这是为了在找不到符合条件的子串时返回整个字符串的长度作为默认值。
    • window_counts 是一个字典,用于记录当前窗口内每个目标字符 'A''S''D''F' 出现的次数,初始值均为0。
  2. 扩展右边界

    for right in range(len(input)):
        window_counts[input[right]] += 1
    
    • 使用一个循环遍历字符串 inputright 表示滑动窗口的右边界。
    • 每次迭代时,将当前字符 input[right] 在 window_counts 中的计数加1。
  3. 检查窗口是否满足替换条件

    while all(window_counts[char] >= needed_replacements[char] for char in 'ASDF'):
        min_length = min(min_length, right - left + 1)
        window_counts[input[left]] -= 1
        left += 1
    
    • 这个 while 循环用于检查当前窗口内的字符计数是否满足 needed_replacements 中的要求。
    • 如果当前窗口满足条件,则更新 min_length 为当前窗口的长度(即 right - left + 1)。
    • 然后将左边界字符 input[left] 的计数减1,并将左边界向右移动一位,继续检查新的窗口是否仍然满足条件。这样做是为了尽量缩小窗口的大小,找到最短的满足条件的子串。
  4. 返回结果

    return min_length
    
    • 最后返回找到的最短子串的长度。如果在整个字符串中都没有找到满足条件的子串,那么 min_length 将保持为初始值,即整个字符串的长度。

源代码如下

def solution(input):
    # 计算理想频次
    ideal_count = len(input) // 4
    
    # 统计当前频次
    current_counts = {char: input.count(char) for char in 'ASDF'}
    
    # 计算需要替换的字符数
    needed_replacements = {char: max(current_counts[char] - ideal_count, 0) for char in 'ASDF'}
    
    # 如果不需要替换,直接返回0
    if sum(needed_replacements.values()) == 0:
        return 0
    
    # 滑动窗口初始化
    left = 0
    min_length = len(input)
    window_counts = {char: 0 for char in 'ASDF'}
    
    # 扩展右边界
    for right in range(len(input)):
        window_counts[input[right]] += 1
        
        # 检查窗口是否满足替换条件
        while all(window_counts[char] >= needed_replacements[char] for char in 'ASDF'):
            min_length = min(min_length, right - left + 1)
            window_counts[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)