首先, 最重要的, 学会如何给区间排序
intervals.sort(key=lambda x:x[0])
56 合并区间
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key=lambda x:x[0])
res = []
for interval in intervals:
if len(res) == 0:
res.append(interval)
continue
a2, b2 = interval
a1, b1 = res[-1]
if a2 > b1:
res.append(interval)
else:
res[-1] = [a1, max(b1, b2)]
return res
很简单, 根据左侧排序后进行模拟就行
435 无重叠区间
给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠
输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key = lambda x:x[0])
res = []
count = 0
for interval in intervals:
a2, b2 = interval
if len(res) == 0:
res.append(interval)
continue
a1, b1 = res[-1]
if a2 >= b1:
res.append(interval)
else:
if b1 > b2:
res[-1] = interval
count += 1
return count
只能说和上一道题一模一样, 但是我们可以用贪心的算法, 每当有重叠时, 舍弃那个右端更大的
57 插入区间
原本一堆区间, 现加一个, 合并.
当然我们可以加了, 排序, 合并, 就和56一样了, 当然复杂了
思路很简单:
- 如果完全在cur左侧, 直接加res
- 如果有交集, 更新cur
- 如果完全在cur右侧, 先加入cur, 把剩下的加了
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
res = []
current_span = newInterval[:]
for i in range(len(intervals)):
print(current_span)
a2, b2 = intervals[i]
if b2 < current_span[0]:
res.append(intervals[i])
continue
if a2 > current_span[1]:
res.append(current_span)
res.extend(intervals[i:])
break
current_span = [min(a2, current_span[0]), max(b2, current_span[1])]
if current_span not in res:
res.append(current_span)
return res
我一开始是没有最后的那个判断的, 实际上很重要, 因为可能存在一个情况s.t. cur一直都没被加进去
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
left, right = newInterval
placed = False
ans = list()
for li, ri in intervals:
if li > right:
# 在插入区间的右侧且无交集
if not placed:
ans.append([left, right])
placed = True
ans.append([li, ri])
elif ri < left:
# 在插入区间的左侧且无交集
ans.append([li, ri])
else:
# 与插入区间有交集,计算它们的并集
left = min(left, li)
right = max(right, ri)
if not placed:
ans.append([left, right])
return ans
官方题解就显得简洁多了, 用一个变量记录cur是否已经被加入进去
452 最少的箭去射爆气球
输入:points = [[10,16],[2,8],[1,6],[7,12]]
输出:2
解释:气球可以用2支箭来爆破:
-在x = 6处射出箭,击破气球[2,8]和[1,6]。
-在x = 11处发射箭,击破气球[10,16]和[7,12]
其实就是合并区间, 但是是合并成更小的
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
points.sort(key = lambda x:x[0])
res = []
for a2, b2 in points:
if len(res) == 0:
res.append([a2, b2])
else:
a1, b1 = res[-1]
if a2 > b1:
res.append([a2, b2])
else:
res[-1] = [a2, min(b1, b2)]
return len(res)