本文已参与「新人创作礼」活动,一起开启掘金创作之路。
合并区间
56. 合并区间 - 力扣(LeetCode) (leetcode-cn.com)
以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
提示:
- 1 <= intervals.length <= 10^4
- intervals[i].length == 2
- 0 <= starti <= endi <= 10^4
解题思路
由于区间[r0,r1]的小标r0,r1是有序的,那么可以把所有区间的下标进行线性处理,按从小到大进行排序处理
每次遇到起始下标r0就加1,终止下标r1就加-1,那么重叠的区间肯定是下标和大于0的,比如[1,3],[2,6]这两个区间,按上面说的处理:
下标线性从小到大处理:
1 -> 2->3->6, 对应的下标次数为:
1 -> 1->-1->-1, 那下标前缀和为:
1 -> 2-> 1-> 0
从这些可以找到规律,在下标2对应的和为2表示从下标2开始有重叠区间,到下标6的下标和为0,表示一个区间的结束。
一个区间的开始到区间结束,下标和都是从0 ->大于0->0
那么我们查找一个区间,从下标和为0的下标是区间起始位置r0,下标和为0的下标是区间结束位置r1。
代码实现
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
res = []
range_cnt = collections.Counter()
for i in intervals:
#起始下标+ 1, 终止下标+ -1
range_cnt[i[0]] += 1
range_cnt[i[1]] += -1
keys = list(range_cnt.keys())
keys.sort()
#s计算到该下标的前缀和
s = 0
r0 = 0
r1 = 0
for i in keys:
if s == 0:
r0 = i
s += range_cnt[i]
if s > 0:
r0 = min(i, r0)
elif s < 0:
r1 = i
else:
r1 = i
res.append([r0, r1])
"""
if s == 0:
res.append([r0, i])
"""
return res