452. 用最少数量的箭引爆气球
题目链接 452. 用最少数量的箭引爆气球 - 力扣(LeetCode)
思路
虽然描述没看懂,但是例子看懂了·
就是要找重叠的区间
-
排序 :将所有气球按照右边界 xend 从小到大排序。
- 排序后,我们优先处理右边界更小的气球,这样能让箭的位置尽可能靠左,覆盖更多后续气球。
-
遍历射箭:
-
初始化第一支箭,射在第一个气球的右边界(这是能射爆它的最右位置,最优选择)。
-
遍历后续气球:如果当前气球的左边界 ≤ 箭的位置,说明会被当前箭射爆,无需新箭;
-
如果左边界 > 箭的位置 ,说明需要新箭,新箭射在当前气球的右边界,箭数 + 1。
-
为什么这个策略正确?
- 按右边界排序后,每次选气球的右边界射箭,能最大化覆盖后续重叠的气球,是全局最优的贪心选择。
提交

python
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
# 边界情况:没有气球,返回0
if not points:
return 0
# 按气球的右边界从小到大排序
points.sort(key=lambda x: x[1])
# 初始化:至少需要1支箭,箭射在第一个气球的右边界
arrows = 1
last_shot = points[0][1]
# 遍历剩余所有气球
for start, end in points[1:]:
# 当前气球左边界 > 上一支箭的位置,需要新箭
if start > last_shot:
arrows += 1
last_shot = end # 新箭射在当前气球右边界
return arrows
435. 无重叠区间
思路
要移除最少的区间 = 保留最多的不重叠区间
贪心策略(最优解)
-
按区间的 右边界从小到大排序
-
依次遍历,保留结束最早的区间,这样能给后面留出更多空间
-
统计最多能保留多少个不重叠区间
-
答案 = 总区间数 - 最多保留的不重叠区间数
-
题目要:移除最少区间
-
等价于:留下最多的、互不重叠的区间
因为:移除最少 = 留下最多
举生活例子:你有很多场会议:
-
1,4
-
2,3
-
3,5
你想参加最多场会议,怎么选?
正常人都会选:
-
先选 结束最早 的:[2,3]
-
再选后面不冲突的:[3,5]
一共参加 2 场,最多。
为什么选结束早的? 因为结束越早,后面剩下时间越多,能塞更多会议。
提交

python
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
if not intervals:
return 0
intervals.sort(key=lambda x:x[1])
keep=1
last_end=intervals[0][1]
for start,end in intervals[1:]:
if start>=last_end:
keep+=1
last_end=end
return len(intervals)-keep
763.划分字母区间
题目链接 763. 划分字母区间 - 力扣(LeetCode)
思路
给你一个字符串,比如:ababcbacadefegdehijhklij
要求:
- 把它切成尽可能多的小段
- 同一个字母,只能出现在其中一个小段里 比如
a出现在第一段,那后面所有段绝对不能再出现 a - 最后返回每一段的长度
每一段必须包含这段里所有字母最后一次出现的位置,才能切!
步骤
-
先扫一遍字符串,记下每个字母最后一次出现在哪里 比如
a最后出现在下标 8,b最后出现在下标 5...... -
再从头遍历字符串
- 记录当前片段能延伸到的最远位置
- 当遍历到这个最远位置时,就可以切一刀!
- 这就是一个合法片段!
字符串:ababcc
-
查每个字母最后出现位置:
- a → 下标 2
- b → 下标 3
- c → 下标 5
-
开始走:
- 走到 a(最远是 2)
- 走到 b(最远更新成 3)
- 走到 a(最远还是 3)
- 走到 b(最远还是 3)现在走到了最远位置 3 → 切一刀!长度 4
继续走:
- 走到 c(最远 5)
- 走到 c(最远 5)走到了最远位置 5 → 切一刀!长度 2
最终结果:[4,2]
提交

python
def partitionLabels(s):
# 1. 先记录每个字符最后一次出现的位置
last = {c: i for i, c in enumerate(s)}
res = []
start = 0 # 片段开始位置
end = 0 # 片段能延伸到的最远位置
# 2. 遍历字符串
for i, c in enumerate(s):
end = max(end, last[c]) # 更新最远位置
# 3. 走到了最远点 → 切分
if i == end:
res.append(i - start + 1)
start = i + 1 # 下一段开始
return res