编号41题解 | 豆包MarsCode AI 刷题

71 阅读3分钟

题目 最小替换子串长度

问题描述:

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

测试样例:
样例1:

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

样例2:

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

问题分析:
思路:
  1. 计算目标频次:由于字符串长度总是4的倍数,所以每个字符的目标频次为 n // 4,其中 n 是字符串的长度。

  2. 统计字符频次:使用 Counter 统计字符串中每个字符的频次。

  3. 滑动窗口:使用滑动窗口技术来找到最短的子串,使得通过替换该子串中的字符,可以使得剩余字符串中每个字符的频次相等。

    • 初始化左右指针 left 和 right,都指向字符串的起始位置。
    • 右指针 right 向右移动,扩大窗口,同时增加窗口内字符的计数。
    • 当窗口内的字符满足条件(即窗口外的字符频次均不超过目标频次)时,左指针 left 开始向右移动,缩小窗口,寻找最小满足条件的窗口。
    • 记录最小窗口的长度。
解题:

使用语言为Python,逐行解释

  1. 导入必要的模块

    from collections import Counter
    

    导入 Counter 类,用于统计字符频次。

  2. 定义函数

    def solution(input):
    
  3. 计算字符串长度和目标频次

    n = len(input)
    target_freq = n // 4
    

    计算字符串的长度 n,并计算每个字符的目标频次 target_freq,即 n // 4

  4. 统计字符频次

    char_count = Counter(input)
    

    使用 Counter 统计输入字符串中每个字符的频次。

  5. 检查是否已经满足条件

    if all(count == target_freq for count in char_count.values()):
        return 0
    

    如果所有字符的频次已经等于目标频次,直接返回0,表示不需要替换任何字符。

  6. 初始化滑动窗口

    left = 0
    min_length = n
    current_count = Counter()
    

    初始化左指针 left 为0,最小子串长度 min_length 为字符串长度 n,当前窗口内字符的计数器 current_count 为空。

  7. 滑动窗口遍历字符串

    for right in range(n):
        current_count[input[right]] += 1
    

    使用右指针 right 从0到 n-1 遍历字符串,每次增加当前窗口内字符的计数。

  8. 检查窗口内字符是否满足条件

    while all(char_count[c] - current_count[c] <= target_freq for c in 'ASDF'):
        min_length = min(min_length, right - left + 1)
        current_count[input[left]] -= 1
        left += 1
    

    当窗口内的字符满足条件(即窗口外的字符频次均不超过目标频次)时,更新最小子串长度 min_length,并尝试缩小窗口,减少左指针所指字符的计数,然后移动左指针 left

  9. 返回最小子串长度

    return min_length
    

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

  10. 测试用例

 if __name__ == "__main__":
     print(solution("ADDF") == 1 )  # True
     print(solution("ASAFASAFADDD") == 3)  # True

总结

通过上述代码实现了通过滑动窗口技术找到最短的子串,使得通过替换该子串中的字符,可以使得剩余字符串中每个字符的频次相等。这种方法的时间复杂度为 O(n),空间复杂度为 O(1)