LeetCode 56,区间合并问题
本文始发于个人公众号:TechFlow,原创不易,求个关注
今天是LeetCode专题的第33篇文章,我们一起来看LeetCode的第56题,它的难度是Medium。
题意
这道题的题意也很简单,只有一句话:“Given a collection of intervals, merge all overlapping intervals.”
interval是间隔、区间的意思,也就是说题目会给我们一系列区间,让我们把这些区间合并在一起。
我们看下题目给的样例来感受一下:
“
Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
“
Input: [[1,4],[4,5]]
Output: [[1,5]]
Explanation: Intervals [1,4] and [4,5] are considered overlapping.
分析
通过观察样例,我们发现题目通过数组给定区间,每个区间有两个端点。两个区间能够合并的条件,就是互相之间有交叉的部分。我们看下下图,这应该很直观。
当两个区间[s1, e1]和[s2, e2]中的e1 >= s2时,这两个区间就可以进行合并。合并之后得到的新区间是[s1, e2]。
但是这存在一个小问题,我们如何能判断第一个区间一定在第二个区间的左侧呢,会不会发生重叠呢?
如果是这种情况那么合并之后的结果就是[s2, e2]了,另外一个问题是,这样的区间一共有N个,我们怎么判断合并的顺序呢?很有可能出现AB两个区间原本不能合并,但是A合并了区间C之后又可以和B合并的情况。如果我们枚举的话会很麻烦,我们不但需要考虑合并的时候会发生的种种情况,还需要考虑合并的发生顺序。而且我们也很难得知是否所有能够合并的区间已经合并完成。
题解
我们梳理一下目前遇到的问题,第一个问题是区间根据位置的不同合并之后的结果可能有多个。第二个问题是区间合并之后会创建新的合并的可能,第三个问题是我们判断当前是否还有合并的可能开销很大。
其中第三个问题是前两个问题导致的,只要解决了其中一个,第三个问题自然迎刃而解。其中第二个问题是无法解决的,因为这是区间合并的天然属性,我们执行区间合并必然会有这样的情况发生。所以我们只能针对第一个问题下手,合并之后的结果可能有多种的本质原因是区间的位置关系可能有多个。A和B合并,A可以出现在B的左侧,也可以出现在B的右侧。再根据区间长短关系,所以才导致了多种结果。
如果我们能够保证A一定出现在B的左侧,那么A和B就只有三种情况。一种是A和B不相交,也就是不能合并。第二种是A和B相交,第三种是A包含B。
我们把图画出来,很容易发现后面两种能够合并的情况其实可以概括成一种,它们合并之后的结果都是[s1, max(e1, e2)]。
既然如此,本题的关键就是区间之间的顺序。假如我们保证了区间的顺序,我们依次合并显然可以很容易得到结果。但是我们怎么得到区间顺序呢?
其实很简单,就是排序,既然区间本来没有顺序,我们对它们排序,不就有顺序了吗?
我们可以规定左侧端点小的区间排在前面,如果两个区间左端点一致,右端点小的靠前。这是什么?这其实就是字典序排序,在Python当中我们可以直接调用sorted对多元素的list进行字典序排序。如果是其他语言,也不麻烦,我们可以自己定义比较算子,一样可以解决。
既然区间有序了,我们只需要从左到右遍历就可以覆盖所有情况了,第三个问题也就解决了。
最后,我们来看下代码,只要想到了排序,这道题并不难。但是初学者往往很难想到排序上,这当中的思维推导过程才是我们需要熟悉的。
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
ret = []
if len(intervals) == 0:
return ret
# 字典序排序
intervals = sorted(intervals)
# l,r表示当前区间的两个端点
l, r = intervals[0]
# 从1开始遍历区间,进行合并
for i in range(1, len(intervals)):
s, e = intervals[i]
# 如果可以合并,维护合并之后的右端点
if s <= r:
r = max(r, e)
else:
# 否则加入答案,将i区间作为当前进行合并的区间
ret.append([l, r])
l, r = s, e
ret.append([l, r])
<span class="hljs-keyword" style="color: #333; font-weight: bold; line-height: 26px;">return</span> ret
结尾
到这里,这道题就结束了,除了排序之外,这道题还可以使用连通分量的思想来做。我们可以枚举所有区间的关系,我们可以把所有区间看成是图上的一个点。只要两个区间可以合并,我们就把它们两个点之间连一条边。这样所有可以合并在一起的区间,就构成了一个连通分量。我们最后遍历这整张图上所有的连通分量就可以拿到所有合并之后的区间结果。和排序比起来,这个算法显然复杂得多,需要建图、连边,然后计算连通分量。并且复杂度也很高,是的算法。我觉得完全没有必要,所以就不多介绍了,感兴趣的同学可以自己了解一下,只要图建好之后,连通分量的求解也不是很复杂。
你看,复杂的算法未必效果就好,还是要适合题目的才是最好的,但什么算法是适合题目的呢?这才是所有问题的关键。这不禁让我想到了电影霍元甲里面,李连杰说的一句话,武功本身没有强弱之别,只是使用武功的武者实力有高下之分。算法也是一样,复杂的算法并不一定就强,灵活运用、理性分析、合理运用才是王道。
今天的文章就到这里,原创不易,需要你一个关注的支持,你的举手之劳对我来说很重要。
LeetCode 56,区间合并问题的更多相关文章
- leetcode 56区间合并
class Solution { public: static bool cmp(vector<int> a,vector<int> b){ ]<b[]; } vecto ...
- 【LeetCode】区间合并
给定一组区间,将所有区间重叠的部分合并起来. e.g. 给出 { [1, 3], [2, 6], [8, 10], [15, 18] },返回 { [1, 6], [8, 10], [15, 18] ...
- LeetCode 56. Merge Intervals 合并区间 (C++/Java)
题目: Given a collection of intervals, merge all overlapping intervals. Example 1: Input: [[1,3],[2,6] ...
- LeetCode 56,57,60,连刷三题不费劲
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第34篇文章,刚好接下来的题目比较简单,很多和之前的做法类似.所以我们今天出一个合集,一口气做完接下来的57.5 ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- HDU 3911 线段树区间合并、异或取反操作
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911 线段树区间合并的题目,解释一下代码中声明数组的作用: m1是区间内连续1的最长长度,m0是区间内连续 ...
- HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Lim ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- POJ 2750 Potted Flower (线段树区间合并)
开始懵逼找不到解法,看了网上大牛们的题解才发现是区间合并... 给你n个数形成一个数列环,然后每次进行一个点的修改,并输出这个数列的最大区间和(注意是环,并且区间最大只有n-1个数) 其实只需要维护 ...
随机推荐
- win下youtube-dl 【ERROR: requested format not available】选下载视频质量的坑--【值得一看】
需求说明(bug出处): 简单说:下载youtube的视频,嵌入翻译好的中文字幕. 详细说(可略过): 阿里的海外服务器需要布一个Web Service---用以接收国内(本地服务器)的请求, 然后用 ...
- python3(二十八)manyExten
""" 多重继承 """ __author__ = 'shaozhiqi' # start ------------------------ ...
- Chrome浏览器架构
通用浏览器架构 它可以是一个具有许多不同线程的进程,也可以是具有几个通过IPC进行通信的多个线程的进程. 一个具有许多不同线程的进程 通过IPC进行通信的多个线程的进程 注意 这些不同的体系结构是实现 ...
- 1.Git 安装
Git的安装 阿里云镜像去下载 阿里云的镜像地址 卸载Git 1.首先在系统环境变量->path->里面去清理掉git相关的环境变量 2.然后控制面板卸载 安装Git 一直下一步即可 使用 ...
- 005-循环结构(上)-C语言笔记
005-循环结构(上)-C语言笔记 学习目标 1.[掌握]switch-case结构 2.[理解]case语句穿透 3.[理解]Xcode断点调试 4.[理解]while循环结构初体验 5.[掌握]w ...
- SpringBoot实现图片上传demo&Nginx进行代理显示
公司项目需要一个图片上传的功能,就图片能上传到服务器(公司用的windows服务器),然后nginx能进行代理访问到就行了,先简单介绍一下nginx,然后再来实现功能. 一.nginx简介 Nginx ...
- 用three.js开发三维地图实例
公司要做智慧消防楼层可视化,需要用到web3d,开源的引擎中先研究了cesium三维地球,但cesium做楼层感觉是大材小用,而且体验也不好,最终选用的是功能强大.更适合小型场景的three. thr ...
- Delphi程序启动参数的读取
Delphi中有两个专门用于读取命令行参数的变量: Paramcount-->用于返回命令行参数的个数 Paramstr数组-->用于返回指定的命令行参数 示例代码 ...
- 怎么用python 3 开发钉钉群机器人
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Python绿色通道 PS:如有需要Python学习资料的小伙伴可以加 ...
- 嘿嘿,我就知道面试官接下来要问我 ConcurrentHashMap 底层原理了,看我怎么秀他
前言 上篇文章介绍了 HashMap 源码后,在博客平台广受好评,让本来己经不打算更新这个系列的我,仿佛被打了一顿鸡血.真的,被读者认可的感觉,就是这么奇妙. 然后,有读者希望我能出一版 Concur ...