力扣452.用最少数量的箭引爆气球【medium】
力扣435.无重叠区间【medium】
力扣763.划分字母区间【medium】
力扣56.合并区间【medium】
一、力扣452.用最少数量的箭引爆气球【medium】
题目链接:力扣452.用最少数量的箭引爆气球
视频链接:代码随想录
题解链接:灵茶山艾府
1、思路
- 对区间的右端点进行升序排序
- 初始化
ans = 0, pre = -inf
- 如果
start <= pre
:说明这个区间已经有箭,跳过 - 如果
start > pre
:说明没有被覆盖住,更新pre = end
,ans += 1
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
2、代码
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
points.sort(key= lambda x:x[1])
ans = 0
pre = -inf
for start,end in points:
if start > pre:
ans += 1
pre = end
return ans
二、力扣435.无重叠区间【medium】
题目链接:力扣435.无重叠区间
视频链接:代码随想录
题解链接:灵茶山艾府
1、思路
- 求移除最少区间使得剩下的区间之间互不重叠 等价于 选出最多区间使得这些区间互不重叠
- 怎样才可以多呢?我们选出右端点最小的作为第一个区间A,这样相当于为后面预留出更多的位置存放区间,这就是贪心的地方
- 选出第一个后,我们也划去了和A有相交部分的区间,从剩下的区间中再选出最小的右端点
- 所以我们的步骤是
- 将区间的右端点升序排序
- 初始化
ans = 0, pre_r = -inf
- 当碰到区间的左端点 >= 上一个区间的右端点的时候,说明碰到了第一个不相交的了,这就是我们下一个要选的区间,
ans += 1 , pre_r = right
,更新区间数ans和右端点的位置 - 最后的答案用区间长度减一下
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
2、代码
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key = lambda x: x[1])
ans = 0
pre_r = -inf
for left, right in intervals:
if left >= pre_r:
ans += 1
pre_r = right
return len(intervals) - ans
三、力扣763.划分字母区间【medium】
题目链接:力扣763.划分字母区间
视频链接:代码随想录
题解链接:灵茶山艾府
1、思路
- 利用字典键的唯一性,确保最终每个字符对应的下标是最后一次出现的位置
- 初始化答案
ans = [ ], start = end = 0
- 记录第一个字母在字符串中最后一次出现的位置更新为end
- 通过for循环遍历,不断延拓更新end【通过比较当前的
end
和last(c)
】,直到end == i
,说明可以切割了,这就是最早可以切割的地方,即贪心的地方 - 那么
i + 1
就是新的start - 同时记录下刚刚切割的片段长度
- 时间复杂度: O ( 2 n ) O(2n) O(2n)
2、代码
class Solution:
def partitionLabels(self, s: str) -> List[int]:
last = {c: i for i,c in enumerate(s)} # 每个字母最后出现的下标
ans = []
start = end = 0
for i,c in enumerate(s):
end = max(end, last[c]) # 更新当前区间右端点的最大值
if end == i: # 当前区间合并完毕
ans.append(end - start + 1)
start = i + 1 # 下一个区间的左端点
return ans
3、代码问题
- {key_expression: value_expression for item in iterable}
四、力扣56.合并区间【medium】
题目链接:力扣56.合并区间
题解链接:灵茶山艾府
1、思路
- 对区间左端点进行升序排序
- 初始化答案 ans = [ ]
- 判断什么时候可以合并?
- 当遍历区间的左端点在处理区间的右端点左端,即有相交,即可以合并
- 合并后还要更新新的右区间
- 怎么表示这个处理区间的右端点呢?即
ans[-1][1]
!这个表示太巧妙了!我本来是想引进两个新的变量表示
- 否则,不可以合并,将其作为新的处理区间
- 即添加到答案中
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
2、代码
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key = lambda x:x[0])
ans = []
for p in intervals:
if ans and p[0] <= ans[-1][1]: # 可以合并
ans[-1][1] = max(ans[-1][1], p[1]) # 更新右端点最大值
else: # 不相交,无法合并
ans.append(p) # 新的合并区间
return ans