Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >常见编程模式之合并区间

常见编程模式之合并区间

作者头像
口仆
发布于 2020-09-03 08:33:01
发布于 2020-09-03 08:33:01
1.3K00
代码可运行
举报
运行总次数:0
代码可运行

4. 合并区间(Merge Intervals)

基本原理及应用场景

合并区间模式是一种处理重叠区间的有效手段。在很多包含区间的问题中,我们可能需要去找出重叠的部分或将重叠部分合并。给定两个区间,其关联方式有如下六种:

在以下场景中,我们可能会用到合并区间:

  • 题目涉及生成只包含互斥区间的列表
  • 题目涉及重叠区间

经典例题

56. 合并区间(Medium)

给出一个区间的集合,请合并所有重叠的区间。

「示例」

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3][2,6] 重叠, 将它们合并为 [1,6].

先基于左边界对区间集合进行排序,这样将区间的关联关系限定在前三种,我们只需要对下面两种重叠情况进行合并即可:

基于上述思想,代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        if len(intervals) < 2: return intervals
        intervals.sort(key = lambda x: x[0]) # 对集合排序(按左边界)
        
        merged = []
        start = intervals[0][0]
        end = intervals[0][1]

        for i in range(1, len(intervals)):
            interval = intervals[i] # 从第二个区间开始,逐个比较
            if interval[0] <= end: # 当前区间的左边界小于上一个区间的右边界,说明有重叠
                end = max(interval[1], end) # 合并后的右边界为两个区间右边界的最大值,左边界为上一个区间的(因为已排序)
                # 合并后继续遍历,直到不重叠再添加到结果中
            else:
                merged.append([start, end]) # 不存在重叠,将上一个区间添加到结果中
                start = interval[0]
                end = interval[1]
        
        merged.append([start, end]) # 将最后一组区间添加到结果中
        return merged
986. 区间列表的交集(Medium)

给定两个由一些「闭区间」组成的列表,每个区间列表都是成对不相交的,并且已经排序。返回这两个区间列表的交集。 (形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b。两个闭区间的交集是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3]。)

「示例」

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入:A = [[0,2],[5,10],[13,23],[24,25]], B = [[1,5],[8,12],[15,24],[25,26]]
输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

我们可以用两个指针分别指向 A 和 B,比较其当前指向的区间。由于 A 和 B 内部的区间均已排序且不相交,所以对于存在重叠的两个区间,较小的末端点只可能与一个区间相交,否则会在列表内部出现两个相交的区间,与题意不符。所以我们只需要按顺序比较区间,存在重叠则合并区间,并移动末端点较小的区间所在列表的指针即可。基于上述思想,可以写出如下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def intervalIntersection(self, A: List[List[int]], B: List[List[int]]) -> List[List[int]]:
        ans = []
        i, j = 0, 0

        while i < len(A) and j < len(B):
            lo = max(A[i][0], B[j][0])
            hi = min(A[i][1], B[j][1])
            if lo <= hi: # 存在重叠
                ans.append([lo, hi])
            
            # 移动较小末端点所在列表的指针,可能存在同时移动的情况
            if hi == A[i][1]:
                i += 1
            if hi == B[j][1]:
                j += 1
        
        return ans
57. 插入区间(Hard)

给出一个无重叠的,按照区间起始端点排序的区间列表。 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

「示例」

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8][3,5],[6,7],[8,10] 重叠。

这道题的一种简单做法是参考 56 题,先把新的区间添加到列表中,然后执行 56 题的代码即可。不过由于本题中给定的是无重叠已排序区间列表,所以再次进行排序是没有必要的,可以仅遍历一次合并即可,具体算法如下:

  • newInterval 之前开始的区间添加到输出
  • 添加 newInterval 到输出,若 newInterval 与输出中的最后一个区间重合则合并他们
  • 一个个添加区间到输出,若有重叠部分则合并他们

对应的代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
        new_start, new_end = newInterval
        idx, n = 0, len(intervals)
        output = []

        # 将所有新区间之前的区间添加到结果中
        while idx < n and new_start > intervals[idx][0]:
            output.append(intervals[idx])
            idx += 1
        
        # 如果输出为空或最后一个区间和新区间不重合
        if not output or output[-1][1] < new_start:
            output.append(newInterval)
        # 如果存在重合,则进行合并
        else: 
            output[-1][1] = max(output[-1][1], new_end)
        
        # 添加之后的区间,存在重合则合并
        while idx < n:
            interval = intervals[idx]
            start, end = interval
            idx += 1
            if output[-1][1] < start:
                output.append(interval)
            else:
                output[-1][1] = max(output[-1][1], end)
        return output
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 口仆 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
​LeetCode刷题实战57:插入区间
https://leetcode-cn.com/problems/insert-interval/
程序员小猿
2021/01/20
3600
​关关的刷题日记99 – Leetcode 56. Merge Intervals
关关的刷题日记99 – Leetcode 56. Merge Intervals 题目 Given a collection of intervals, merge all overlapping intervals. For example, Given [1,3],[2,6],[8,10],[15,18], return [1,6],[8,10],[15,18]. 题目的意思是给出一个区间集合,让我们合并所有重叠区间。 思路 首先我们要对集合进行从小到大排序,因为区间是自己定义的数据结构,所以我们要
WZEARW
2018/04/13
5940
【Leetcode】57. 插入区间
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
Leetcode名企之路
2018/09/12
3700
【一天一大 lee】插入区间 (难度:困难) - Day20201104
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
前端小书童
2020/11/11
3030
【一天一大 lee】插入区间 (难度:困难) - Day20201104
LeetCode 57. 插入区间(一次遍历)
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
Michael阿明
2020/07/13
3290
算法刷题-插入区间、杨辉三角、移除链表元素
给你一个** 无重叠的**_ ,_按照区间起始端点排序的区间列表。 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
共饮一杯无
2023/02/10
1970
算法刷题-插入区间、杨辉三角、移除链表元素
LeetCode 57. 插入区间
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
韩旭051
2020/11/24
3390
【python-leetcode57-区间合并】插入区间
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
西西嘛呦
2020/08/26
6410
LeetCode134|插入区间
给出一个无重叠的 ,按照区间起始端点排序的区间列表。在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
码农王同学
2020/11/16
3100
Leetcode No.56 合并区间
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
week
2021/05/06
3960
LeetCode - #57 插入区间
我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。
Swift社区
2022/07/05
2580
插入区间\
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
狼啸风云
2023/11/09
2340
插入区间\
LintCode-30. 插入区间
给出一个无重叠的按照区间起始端点排序的区间列表。 在列表中插入一个新的区间,你要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
悠扬前奏
2019/05/31
4250
算法细节系列(26):区间
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014688145/article/details/72841132
用户1147447
2019/05/26
4880
Data Structures and Algorithms Basics(003):Binary search
二分查找要求:线性表是有序表,即表中结点按关键字有序,并且要用向量作为表的存储结构。
用户5473628
2019/08/08
3300
☆打卡算法☆LeetCode 57、插入区间 算法解析
“给定一个无重叠的区间列表,在列表中插入一个新的区间,确保列表中的区间仍然有序且不重叠。”
恬静的小魔龙
2022/08/07
2170
☆打卡算法☆LeetCode 57、插入区间  算法解析
合并区间(LeetCode 56)
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
恋喵大鲤鱼
2023/12/28
6570
合并区间(LeetCode 56)
leetcode刷题(76)—— 56. 合并区间
输入: [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18]] 解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. 示例 2:
老马的编程之旅
2022/06/22
1920
leetcode刷题(76)—— 56. 合并区间
57. 插入区间
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
张伦聪zhangluncong
2022/10/26
2370
LeetCode - #56 合并区间(Top 100)
我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。
Swift社区
2022/07/05
2990
相关推荐
​LeetCode刷题实战57:插入区间
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验