题目描述
思路解析动画文字版
先记每个字符最后出现位置,当前片段的 end 是这些最后位置的最大值。
1. 先记每个字母最后出现的位置:贪心关键:一段必须装下段内每个字母的所有出现,所以只要覆盖到每个字母最后一次出现的下标即可。
2. 从 a 开始,end 拉到 4:i=0 是 a,last(a)=4 → 段尾 end=4,这一段至少要延到下标 4。
3. 中间字母都没超出 end:i 一路扫到 3:途中 b(last3)、c(last2)、b 的最后位置都 ≤ 4,end 不变。
4. i 追上 end,切第一刀:i 走到 4,正好 i == end:从这里切开,第一段 [0,4] 长度 5。
5. 新段从 d,end=7:新段从 d 开始,last(d)=7 → end=7。
6. 关键帧 · e 把 end 推到 8:看到 e,last(e)=8 比当前 end=7 更远 → end 被推到 8。这就是“边扫边把段尾扩到最远”的核心。
7. i 追上 end,切第二刀:i=8 == end,切第二刀:第二段 [5,8] 长度 4。
8. 第三段 f,i 一上来就 == end:第三段从 f 起,last(f)=9,i 一上来就 i == end,单独成一段。
9. 答案:三段长度 [5, 4, 1],每段都恰好覆盖段内字母的最后出现位置。
这类题不是枚举所有切法,而是维护当前片段必须覆盖到的最远位置。
边界三连:三种极端先过:不重复→全切碎;有跨段重复→被迫合并。
面试官常追问:三个高频追问,答法记牢。
参考代码
class Solution: def partitionLabels(self, s): last = {ch: i for i, ch in enumerate(s)} ans = [] start = end = 0 for i, ch in enumerate(s): end = max(end, last[ch]) if i == end: ans.append(end - start + 1) start = i + 1 return ans复杂度
- 时间复杂度:O(n),扫两遍字符串(建表 + 划分),共约 2n
- 空间复杂度:O(1),last 表最多 26 个字母,常数额外空间
可套用的代码模板
这段代码可以按 LeetCode Python 模板直接提交;变量名和动画里的核心状态保持一致。
Python
# 划分字母区间骨架 · 最远边界贪心last = {字母 -> 它最后出现的下标}start = end = 0for i, ch in enumerate(s): end = max(end, last[ch]) # 段尾扩到当前字母最远处 if i == end: # i 追上段尾 -> 这一段闭合 记录长度 end - start + 1 start = i + 1易错点
面试追问把动画讲成自己的话
追问为什么记“最后位置”而不是出现次数?
追问为什么 i==end 就能安全切?
追问复杂度?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
有效的括号字符串
LeetCode 678 · 中等 · 沿着 贪心 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题