最小替换子串长度
问题描述
小F得到了一个特殊的字符串,这个字符串只包含字符A、S、D、F,其长度总是4的倍数。他的任务是通过尽可能少的替换,使得A、S、D、F这四个字符在字符串中出现的频次相等。求出实现这一条件的最小子串长度。
解题思路
由于这道题目给了一个只包含 A、S、D 和 F 的字符串,需要我们通过最少的替换来使这四个字符的出现次数相等。由于字符串长度是4的倍数,因此每个字符最终的目标频次为 n / 4。利用滑动窗口,我们可以将整个字符串分为两部分窗口内需要替换的字符串和窗口外的剩余部分,而解决问题的核心就在于找到最小的滑动窗口,使得窗口外字符串符合频次。
滑动窗口核心逻辑是动态调整子串的起始和结束位置,通过不断地收缩和扩展窗口,检查窗口外的字符是否满足目标频次。因此需要初始化窗口边界移动调整然后对当前窗口内的字符频次计数,然后检查窗口外字符是否满足条件,每当窗口满足条件时,记录当前窗口长度,并尝试缩小窗口以寻找更小的长度。
代码如下
from collections import Counter
def solution(s):
n = len(s)
target = n // 4 # 每个字符的目标频次
freq = Counter(s) # 初始字符频次统计
# 达到频次直接返回
if all(freq[char] == target for char in 'ASDF'):
return 0
# 滑动窗口设置
left = 0
min_length = n
current_freq = Counter()
# 遍历整个字符串,动态调整窗口
for right in range(n):
current_freq[s[right]] += 1
# 检查窗口外字符频次是否满足
while left <= right and all(freq[char] - current_freq[char] <= target for char in 'ASDF'):
#
min_length = min(min_length, right - left + 1)
current_freq[s[left]] -= 1
left += 1
return min_length
if __name__ == "__main__":
print(solution("ADDF") == 1)
print(solution("ASAFASAFADDD") == 3)
总结
对于处理连续子数组或子串问题,滑动窗口是一个比较好的算法技巧,通过动态调整窗口的起始和结束位置,避免了全局遍历,提高效率。在滑动窗口设置中中,边界条件的设置至关重要,需要格外注意。初步学习,将原始复杂问题分解为几个子问题来逐一解决
学习建议
最后,自己需要牢记,做题并不是单纯地积累题目数量,而是培养解决问题的能力,做题的核心是理解,而不是记忆,每次做题,都要抱着“思考为什么”的态度,深入理解每个步骤,保持耐心,持续积累。 同时需要记录错题,定期复盘,做错的题收藏记录,分析错误原因,每周或每月定期回顾,同时还要针对错题,举一反三,尝试延展出类似题型,刷题不是单纯的重复,而是思维的拓展。巩固相关知识,看是否真正掌握,同时要避免陷入误区,纸上得来终觉浅,绝知此事要躬行,一定要亲手敲代码,只有亲手敲的才是自己的代码,即使思路很清晰,也要动手实现,过程中才有可能会发现细节问题。同时由易到难,合理分配好自己的时间,制定合理的学习计划,方能有所提高。