494 字
2 分钟
代码随想录算法训练营第二十六天 | 贪心算法 Part04
区间贪心算法
本节聚焦于区间贪心类问题:以区间的右端点排序是解决“重叠最小化”或“最少操作”的核心策略。
452. 用最少数量的箭引爆气球
LeetCode 452. Minimum Number of Arrows to Burst Balloons
- 按右端点排序;
- 每次选一支箭射当前区间的右端点,跳过所有与之重叠的气球;
- 不重叠则再射一箭。
class Solution: def findMinArrowShots(self, points: List[List[int]]) -> int: if not points: return 0
# 按气球的右边界升序排列 points.sort(key=lambda x: x[1])
count = 1 # 至少一支箭 x_end = points[0][1] # 当前箭射的位置
for point in points: start = point[0] if start > x_end: # 当前气球与上一支箭不重叠,需要额外一支箭 count += 1 x_end = point[1]
return count
435. 无重叠区间
LeetCode 435. Non-overlapping Intervals
- 和上一题类似,按右端点升序;
- 每次选能不重叠的最多区间数;
- 用总数减去最多可选数,就是最少删除数。
class Solution: def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int: n = len(intervals) if not intervals: return 0
# 按右端点升序排序 intervals.sort(key=lambda x: x[1])
count = 1 # 至少保留一个不重叠区间 x_end = intervals[0][1]
for interval in intervals: start = interval[0] if start >= x_end: # 当前区间不重叠,可以保留 count += 1 x_end = interval[1]
# 要删除的区间数 = 总数 - 可保留数 return n - count
763. 划分字母区间
LeetCode 763. Partition Labels
- 记录每个字符最后出现的位置;
- 从左到右遍历更新当前分区的最大边界;
- 当遍历到最大边界位置时,可以分区。
class Solution: def partitionLabels(self, s: str) -> List[int]: # 记录每个字母最后一次出现的位置 last_pos = {ch: i for i, ch in enumerate(s)}
res = [] start = end = 0
for i, ch in enumerate(s): # 当前分区最远可以延伸到 ch 的最后位置 end = max(end, last_pos[ch]) if i == end: # 当前 i 达到分区边界,可以切分 res.append(end - start + 1) start = i + 1
return res
代码随想录算法训练营第二十六天 | 贪心算法 Part04
https://fuwari.vercel.app/posts/code_musings_day_twenty-six/