leetcode 56. 合并区间

422 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

合并区间

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

参考

吃🐳!🤷‍♀️竟然一眼秒懂合并区间! - 合并区间 - 力扣(LeetCode) (leetcode-cn.com)