合并区间
给出一个区间的集合,请合并所有重叠的区间。
示例 1:
输入: intervals = ,,,) 输出: ((1,6),,) 解释: 区间 (1,3) 和 重叠, 将它们合并为 (1,6).
示例 2:
输入: intervals = ,(4,5)) 输出: ((1,5)) 解释: 区间 (1,4) 和 (4,5) 可被视为重叠区间 注意:输入类型已于2019年4月15日更改请重置默认代码定义以获取新方法签名
提示:
intervals(0) lt,= intervals(1)
。middot,
大家应该都感觉到了,此题一定要排序,那么按照左边界排序,还是右边界排序呢。
都可以!
那么我按照左边界排序,排序之后局部最优:每次合并都取最大的右边界,这样就可以合并更多的区间了,整体最优:合并所有重叠的区间。
局部最优可以推出全局最优,找不出反例,试试贪心。
那有同学问了,本来不就应该合并最大右边界么,这和贪心有啥关系。
有时候贪心就是常识!哈哈
按照左边界从小到大排序之后,如果 intervals(0) lt, intervals(i — 1)(1) 即intervals左边界 lt, intervals(i — 1)右边界,则一定有重复,因为intervals的左边界一定是大于等于intervals(i — 1)的左边界。
即:intervals的左边界在intervals(i — 1)左边界和右边界的范围内,那么一定有重复!
这么说有点抽象,看图:
合并区间
知道如何判断重复之后,剩下的就是合并了,如何去模拟合并区间呢。
其实就是用合并区间后左边界和右边界,作为一个新的区间,加入到result数组里就可以了如果没有合并就把原区间加入到result数组
C++代码如下:
classSolutionpublic://按照区间左边界从小到大排序staticboolcmpreturna(0)lt,b(0),vectorlt,vectorgt,merge(vectorlt,vectorgt,amp,intervals)vectorlt,vectorgt,result,if(intervals.size()0)returnresult,sort(intervals.begin(),intervals.end(),cmp),boolflag=false,//标记最后一个区间有没有合并intlength=intervals.size(),for(inti=1,ilt,length,i++)intstart=intervals(i—1)(0),//初始为i—1区间的左边界intend=intervals(i—1)(1),//初始i—1区间的右边界while(ilt,lengthamp,amp,intervals(i)(0)lt,=end)//合并区间end=max(end,intervals(i)(1)),//不断更新右区间if(ilength—1)flag=true,//最后一个区间也合并了i++,//继续合并下一个区间//start和end是表示intervals(i—1)的左边界右边界,所以最优intervals(i)区间是否合并了要标记一下result.push_back(start,end),//如果最后一个区间没有合并,将其加入resultif(flagfalse)result.push_back(intervals(length—1)(0),intervals(length—1)(1)),returnresult,,
当然以上代码有冗余一些,可以优化一下,如下:
classSolutionpublic:vectorlt,vectorgt,mergevectorlt,vectorgt,result,if(intervals.size()0)returnresult,//排序的参数使用了lamda表达式sort(intervals.begin(),intervals.end(),()(constvectoramp,a,constvectoramp,b)returna(0)lt,b(0),),result.push_back(intervals(0)),for(inti=1,ilt,intervals.size(),i++)if(result.back()(1)gt,=intervals(i)(0))//合并区间result.back()(1)=max(result.back()(1),intervals(i)(1)),elseresult.push_back(intervals(i)),returnresult,, 时间复杂度:O(nlogn) ,有一个快排 空间复杂度:O(1),我没有算result数组(返回值所需容器占的空间) 总结
对于贪心算法,很多同学都是:如果能凭常识直接做出来,就会感觉不到自己用了贪心, 一旦第一直觉想不出来, 可能就一直想不出来了。
跟着「代码随想录」刷题的录友应该感受过,贪心难起来,真的难。
那应该怎么办呢。
正如我贪心系列开篇词关于贪心算法,你该了解这些!中讲解的一样,贪心本来就没有套路,也没有框架,所以各种常规解法需要多接触多练习,自可是然才会想到。
「代码随想录」会把贪心常见的经典题目覆盖到,大家只要认真学习打卡就可以了。
其他语言版本
Java
Python
classSolution:defmerge))—gt,List(List(int)):iflen(intervals)0:returnintervalsintervals.sort(key=lambdax:x(0))result=()result.append(intervals(0))foriinrange(1,len(intervals)):last=result(—1)iflast(1)gt,=intervals(i)(0):result(—1)=(last(0),max(last(1),intervals(i)(1)))else:result.append(intervals(i))returnresult
Go
funcmerge()int)()()int//先从小到大排序sort.Slice(intervals,func(i,jint)boolreturnintervals(i)(0)lt,intervals(j)(0))//再弄重复的fori:=0,ilt,len(intervals)—1,i++ifintervals(i)(1)gt,=intervals(i+1)(0)intervals(i)(1)=max(intervals(i)(1),intervals(i+1)(1))//赋值最大值intervals=append(intervals(:i+1),intervals(i+2:)...)i——returnintervalsfuncmax(a,bint)intifagt,breturnareturnb
Javascript
varmerge=functionintervals.sort((a,b)=gt,a(0)—b(0)),letprev=intervals(0)letresult=()for(leti=0,ilt,intervals.length,i++)letcur=intervals(i)if(cur(0)gt,prev(1))result.push(prev)prev=curelseprev(1)=Math.max(cur(1),prev(1))result.push(prev)returnresult,
版本二:左右区间
/***paramnumberintervals*returnnumber*/varmerge=function(intervals)letn=intervals.length,if(nlt,2)returnintervals,intervals.sort((a,b)=gt,a(0)—b(0)),letres=,left=intervals(0)(0),right=intervals(0)(1),for(leti=1,ilt,n,i++)if(intervals(i)(0)gt,right)res.push((left,right)),left=intervals(i)(0),right=intervals(i)(1),elseright=Math.max(intervals(i)(1),right),res.push((left,right)),returnres,,
。郑重声明:此文内容为本网站转载企业宣传资讯,目的在于传播更多信息,与本站立场无关。仅供读者参考,并请自行核实相关内容。