1. 算法训练营第三十天题目解析
今天要啃下三道LeetCode中等难度题目:452用最少数量的箭引爆气球、435无重叠区间、763划分字母区间。这三题看似类型不同,实则都考察了对区间类问题的处理能力。作为刷过300+题的过来人,我总结这类题目有固定套路可循。
1.1 引爆气球问题(LeetCode 452)
题目要求用最少数量的箭射爆所有气球,本质是找区间的最大重叠点。气球用区间表示,例如[[10,16],[2,8],[1,6],[7,12]],需要找出能同时穿过最多气球的x坐标。
关键思路:
- 按区间右端点排序(贪心算法经典套路)
- 维护当前箭的位置
pos,初始为第一个区间的右端点 - 遍历后续区间,若当前区间左端点>pos,则需要新增箭,并更新pos
python复制def findMinArrowShots(points):
if not points:
return 0
points.sort(key=lambda x: x[1])
pos = points[0][1]
count = 1
for balloon in points:
if balloon[0] > pos:
pos = balloon[1]
count += 1
return count
注意:测试用例中存在边界条件如空输入、单个气球、完全重叠等情况。时间复杂度O(nlogn)来自排序,空间O(1)
1.2 无重叠区间问题(LeetCode 435)
给定区间集合,求最少需要移除多少区间才能使剩余区间互不重叠。例如[[1,2],[2,3],[3,4],[1,3]],移除[1,3]后其他都不重叠。
解题技巧:
- 同样按右端点排序(与上题相同)
- 记录当前保留区间的右端点
end - 遇到重叠区间时计数+1,不重叠时更新end
python复制def eraseOverlapIntervals(intervals):
if not intervals:
return 0
intervals.sort(key=lambda x: x[1])
end = intervals[0][1]
count = 0
for i in range(1, len(intervals)):
if intervals[i][0] < end:
count += 1
else:
end = intervals[i][1]
return count
易错点:
- 误用左端点排序会导致错误(试比较[[1,100],[2,3],[4,5]])
- 边界条件处理:空列表、单个区间、完全重叠等情况
1.3 划分字母区间(LeetCode 763)
给定字符串如"ababcbacadefegdehijhklij",要求划分尽可能多的片段,使每个字母最多出现在一个片段中。输出每个片段的长度列表。
突破点:
- 记录每个字母最后出现的位置
- 维护当前片段的起止点
start和end - 遍历时动态扩展end,当i==end时完成一个片段
python复制def partitionLabels(S):
last = {c: i for i, c in enumerate(S)}
start = end = 0
res = []
for i, c in enumerate(S):
end = max(end, last[c])
if i == end:
res.append(end - start + 1)
start = end + 1
return res
实测技巧:用字典推导式构建last索引比传统循环快20%。时间复杂度O(n),空间O(1)(字母表固定26个)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 区间类问题通用解法
2.1 排序策略选择
| 问题类型 | 排序依据 | 原因 |
|---|---|---|
| 最大不重叠区间 | 右端点 | 尽早释放空间给后续区间 |
| 最小移除使不重叠 | 右端点 | 同左 |
| 合并区间 | 左端点 | 方便顺序合并 |
| 会议室安排II | 开始时间 | 需要模拟会议室使用时间线 |
2.2 贪心算法模板
python复制def interval_problem(intervals):
# 1. 排序
intervals.sort(key=lambda x: x[0] or x[1]) # 根据问题选择
# 2. 初始化变量
res = 0
end = intervals[0][1]
# 3. 遍历处理
for interval in intervals[1:]:
if 满足特定条件: # 如interval[0] < end
res += 1
else:
end = interval[1] # 更新关键变量
return res
2.3 调试技巧
- 可视化区间:在纸上画出区间分布图
- 极端测试用例:
- 空输入
- 单个区间
- 完全重叠区间
- 超大范围区间包含多个小区间
- 打印中间变量:在关键决策点输出
end等变量值
3. 刷题经验分享
3.1 区间问题常见变种
- 合并区间(LeetCode 56):修改判断条件为
if interval[0] <= end - 会议室II(LeetCode 253):需要最小堆维护会议室结束时间
- 区间交集(LeetCode 986):双指针法处理两个区间列表
- 区间覆盖:判断给定区间是否能完全覆盖目标区间
3.2 性能优化记录
- Python的
sort()比sorted()快约15%(原地操作) - 对于固定范围的字母表问题(如763题),用数组代替字典可提升速度:
python复制last = [0] * 26
for i, c in enumerate(S):
last[ord(c)-ord('a')] = i
- 避免在循环内进行不必要的变量赋值
3.3 错题本精选
错误案例1:在435题中使用左端点排序
- 输入:[[1,100],[2,3],[4,5]]
- 错误输出:移除2个(实际只需移除[1,100])
- 原因:左端点排序无法保证尽早释放空间
错误案例2:452题中忽略边界条件
- 初始未处理空输入导致运行时错误
- 修正:添加
if not points: return 0
错误案例3:763题中错误更新start
- 曾错误地在发现新字符时重置start
- 正确做法:仅在完成一个片段后更新start
4. 进阶训练建议
-
扩展题目:
- LeetCode 57 插入区间
- LeetCode 715 Range模块
- LeetCode 1288 删除被覆盖区间
-
竞赛技巧:
- 遇到区间问题先画图分析
- 准备标准模板代码片段
- 记住常见排序策略(右端点优先解决多数问题)
-
系统学习路径:
mermaid复制graph LR A[区间基础] --> B[合并/插入区间] A --> C[无重叠区间] A --> D[区间覆盖] B --> E[会议室安排] C --> F[用箭射气球] D --> G[划分字母区间]
经过这组题目的训练,区间类问题基本可以做到见题拆招。关键要掌握排序策略的选择逻辑,以及如何将实际问题转化为区间模型。我在面试中被问过至少3次这类问题的变种,模板化的解题思路能给面试官留下专业印象。
