题目描述
思路解析动画文字版
枚举每个子串再数频率会反复扫描。
窗口长度减去窗口内最高频字符数,就是需要替换的字符数;超过 k 才缩左边。
1. 窗口合法条件:滑动窗口:窗口里保留出现最多的字符,其余全替换。要替换的数 = 窗口长 − 最高频,只要 ≤ k=1 就合法。
2. 窗口 AAB · 替换 1 个:窗口 AAB:最高频 A×2,要替换 = 3−2 = 1 ≤ 1 → 合法,长度 3。
3. 窗口 AABA · 长度 4:右扩成 AABA:最高频 A×3,要替换 = 4−3 = 1 ≤ 1 → 合法,长度 4(目前最长)。
4. 关键帧 · 替换数 > k → 收缩:关键帧:再扩成 AABAB → 最高频 A×3,要替换 = 5−3 = 2 > k=1 → 不合法!左指针右移收缩窗口,直到重新合法。
5. 收缩后继续 · 最长 = 4:l 右移一格、对应字符计数减一,窗口缩到 ABAB(长 4)重新合法,继续右扩。整个过程最长合法窗口 = 4。
6. 答案 4:答案 4:把 AABA 里的 1 个 B 替换成 A → AAAA,长度 4。
一句话记住:窗口长度减去窗口内最高频字符数,就是需要替换的字符数;超过 k 才缩左边。
边界三连:三种边界先想清楚。
面试追问 1:核心思路。
面试追问 2:复杂度分析。
面试追问 3:maxCnt 不减的原因。
这题学完不要乱跳,下一步去对应专题 /leetcode-animation/ds?k=slidingwindow 连刷同类题;卡住时用 AI 答疑问“我的状态定义哪里不稳”。
参考代码
class Solution: def characterReplacement(self, s, k): cnt, l, best, maxCnt = {}, 0, 0, 0 for r, ch in enumerate(s): cnt[ch] = cnt.get(ch, 0) + 1 maxCnt = max(maxCnt, cnt[ch]) while r - l + 1 - maxCnt > k: cnt[s[l]] -= 1; l += 1 best = max(best, r - l + 1) return best复杂度
- 时间复杂度:O(n),左右指针各只前进 n 步
- 空间复杂度:O(1),计数用固定 26 大小的数组
可套用的代码模板
骨架:右扩计数,(窗口长−最高频)>k 就左移收缩,记最长合法窗口。
Python
# 替换后最长重复字符骨架l = maxCnt = best = 0; cnt = {}for r, ch in enumerate(s): cnt[ch] += 1; maxCnt = max(maxCnt, cnt[ch]) while (r - l + 1) - maxCnt > k: # 要替换的 > k → 收缩 cnt[s[l]] -= 1; l += 1 best = max(best, r - l + 1)return best易错点
面试追问把动画讲成自己的话
追问核心思路是什么?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
字符串的排列
LeetCode 567 · 中等 · 沿着 滑动窗口 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题