题目 最小替换子串长度
问题描述:
小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。
测试样例:
样例1:
输入:
input = "ADDF"
输出:1
样例2:
输入:
input = "ASAFASAFADDD"
输出:3
问题分析:
思路:
-
计算目标频次:由于字符串长度总是4的倍数,所以每个字符的目标频次为
n // 4,其中n是字符串的长度。 -
统计字符频次:使用
Counter统计字符串中每个字符的频次。 -
滑动窗口:使用滑动窗口技术来找到最短的子串,使得通过替换该子串中的字符,可以使得剩余字符串中每个字符的频次相等。
- 初始化左右指针
left和right,都指向字符串的起始位置。 - 右指针
right向右移动,扩大窗口,同时增加窗口内字符的计数。 - 当窗口内的字符满足条件(即窗口外的字符频次均不超过目标频次)时,左指针
left开始向右移动,缩小窗口,寻找最小满足条件的窗口。 - 记录最小窗口的长度。
- 初始化左右指针
解题:
使用语言为Python,逐行解释
-
导入必要的模块
from collections import Counter导入
Counter类,用于统计字符频次。 -
定义函数
def solution(input): -
计算字符串长度和目标频次
n = len(input) target_freq = n // 4计算字符串的长度
n,并计算每个字符的目标频次target_freq,即n // 4。 -
统计字符频次
char_count = Counter(input)使用
Counter统计输入字符串中每个字符的频次。 -
检查是否已经满足条件
if all(count == target_freq for count in char_count.values()): return 0如果所有字符的频次已经等于目标频次,直接返回0,表示不需要替换任何字符。
-
初始化滑动窗口
left = 0 min_length = n current_count = Counter()初始化左指针
left为0,最小子串长度min_length为字符串长度n,当前窗口内字符的计数器current_count为空。 -
滑动窗口遍历字符串
for right in range(n): current_count[input[right]] += 1使用右指针
right从0到n-1遍历字符串,每次增加当前窗口内字符的计数。 -
检查窗口内字符是否满足条件
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。 -
返回最小子串长度
return min_length返回找到的最小子串长度。
-
测试用例
if __name__ == "__main__":
print(solution("ADDF") == 1 ) # True
print(solution("ASAFASAFADDD") == 3) # True
总结
通过上述代码实现了通过滑动窗口技术找到最短的子串,使得通过替换该子串中的字符,可以使得剩余字符串中每个字符的频次相等。这种方法的时间复杂度为 O(n),空间复杂度为 O(1)