题目描述
思路解析动画文字版
记住「右扩加和、超预算就左缩减和、每步刷新最长」,下面每一位都在套它。
这一行是每位的代价(s 全 a,t 第 i 位离 a 多远就是 cost[i])。窗口从空开始,右指针从左往右一格格扩。
右指针到第 0 位(t='d',代价 3),加进窗口,和变成 3。仍在预算 5 内,窗口合法。
窗口 [0, 0] 合法,长度 1。比之前更长,刷新 ans=1。
右指针到第 1 位(t='b',代价 1),加进窗口,和变成 4。仍在预算 5 内,窗口合法。
窗口 [0, 1] 合法,长度 2。比之前更长,刷新 ans=2。
右指针到第 2 位(t='b',代价 1),加进窗口,和变成 5。仍在预算 5 内,窗口合法。
窗口 [0, 2] 合法,长度 3。比之前更长,刷新 ans=3。
右指针到第 3 位(t='b',代价 1),加进窗口,和变成 6。超了预算 5(红),需要左缩。
把左指针右移 1 步、依次减掉移出位的代价,窗口和回到 3(≤5)。现在窗口 [1, 3] 长度 3。没超过最长 ans=3。
右指针到第 4 位(t='b',代价 1),加进窗口,和变成 4。仍在预算 5 内,窗口合法。
窗口 [1, 4] 合法,长度 4。比之前更长,刷新 ans=4。
右指针到第 5 位(t='b',代价 1),加进窗口,和变成 5。仍在预算 5 内,窗口合法。
窗口 [1, 5] 合法,长度 5。比之前更长,刷新 ans=5。
右指针到第 6 位(t='e',代价 4),加进窗口,和变成 9。超了预算 5(红),需要左缩。
把左指针右移 4 步、依次减掉移出位的代价,窗口和回到 5(≤5)。现在窗口 [5, 6] 长度 2。没超过最长 ans=5。
右指针到第 7 位(t='c',代价 2),加进窗口,和变成 7。超了预算 5(红),需要左缩。
把左指针右移 2 步、依次减掉移出位的代价,窗口和回到 2(≤5)。现在窗口 [7, 7] 长度 1。没超过最长 ans=5。
右指针到第 8 位(t='d',代价 3),加进窗口,和变成 5。仍在预算 5 内,窗口合法。
窗口 [7, 8] 合法,长度 2。没超过最长 ans=5。
右指针到第 9 位(t='b',代价 1),加进窗口,和变成 6。超了预算 5(红),需要左缩。
把左指针右移 1 步、依次减掉移出位的代价,窗口和回到 4(≤5)。现在窗口 [8, 9] 长度 2。没超过最长 ans=5。
扫完全程,最长的合法窗口是绿色这 5 位(代价和 5 ≤ 5),所以答案 5。左右指针各只走一遍,O(n)。
边界先想清:零代价整串过、单位高代价只取 1、空串为 0。
面试常考:辨析「最长 vs 最短」窗口的左缩时机、以及代价非负这个前提。
参考代码
class Solution: def equalSubstring(self, s: str, t: str, maxCost: int) -> int: left = cost = ans = 0 for right, (a, b) in enumerate(zip(s, t)): cost += abs(ord(a) - ord(b)) while cost > maxCost: cost -= abs(ord(s[left]) - ord(t[left])) left += 1 ans = max(ans, right - left + 1) return ans复杂度
- 时间:O(n),左右指针各只前进一遍
- 空间:O(1),只用 left/sum/ans 几个变量
易错点
面试追问把动画讲成自己的话
追问这题的滑动窗口和「最小覆盖子串」那类有何异同?
追问如果代价可能为负会怎样?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
包含所有三种字符的子字符串数目
LeetCode 1358 · 中等 · 沿着 滑动窗口套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题