关于滑动窗口算法--最小替换字串长度

130 阅读3分钟

个人觉得日常遇到的关于滑动窗口的算法题主要分两种:

固定窗口大小的滑动窗口

在固定窗口大小的滑动窗口问题中,窗口的大小是预先定义好的,不会改变。这种类型的问题是相对简单的,因为一旦确定了窗口的大小,就可以直接遍历数组或列表,每次移动窗口一个元素的位置。常见的问题包括:

  1. 最大/最小子数组和:给定一个数组和一个固定大小的窗口,找到所有可能的窗口的最大/最小和。
  2. 窗口内元素的统计:例如,统计窗口内奇数或偶数元素的数量。
  3. 窗口内元素的频率统计:统计窗口内每个元素出现的次数。

解决这类问题的关键在于维护窗口内的状态,以便在窗口滑动时能够快速更新状态。通常可以使用队列、双端队列(deque)或哈希表来维护窗口内的状态。

动态窗口大小的滑动窗口

动态窗口大小的滑动窗口问题则更为复杂,因为窗口的大小不是固定的,而是根据某些条件动态变化的。这类问题通常涉及到在窗口内寻找满足特定条件的子数组或子串。常见的问题包括:

  1. 无重复字符的最长子串:找到最长的不包含重复字符的子串。
  2. 包含所有字符的最短子串:给定一个字符串和一个字符集合,找到包含所有字符集合中字符的最短子串。
  3. 滑动窗口内的特定条件:例如,找到窗口内所有元素的乘积小于等于给定值的最大窗口。

解决这类问题的关键在于如何高效地扩展和收缩窗口,同时维护窗口内的状态。常用的数据结构包括:

  • 双端队列(deque) :用于维护窗口内元素的顺序,以便快速找到窗口的边界。
  • 哈希表:用于快速查找和更新窗口内元素的频率。
  • 前缀和/前缀最大/最小值:用于快速计算窗口内元素的和、最大值或最小值。

在解决动态窗口大小的滑动窗口问题时,通常需要维护一个滑动窗口的左右指针,并根据特定条件来移动这些指针。例如,当窗口内不满足条件时,移动左指针来缩小窗口;当窗口内满足条件但需要寻找更优解时,移动右指针来扩展窗口。一般常见的是右指针实现扩张,通过扩张不断找到复核人要求的字符串,然后左指针实现收缩,寻求当前字符串下的最小的边界。

下面关于动态的滑动窗口给出题目,感兴趣的可以看下(掘金链接):最小替换子串长度 - MarsCode

问题描述

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


测试样例

样例1:

输入:input = "ADDF"

输出:1

样例2:

输入:input = "ASAFASAFADDD"

输出:3

样例3:

输入:input = "SSDDFFFFAAAS"

输出:1

样例4:

输入:input = "AAAASSSSDDDDFFFF"

输出:0

样例5:

输入:input = "AAAADDDDAAAASSSS"

输出:4

求解代码: