[LeetCode] Merge Interval系列,题:Insert Interval,Merge Intervals
Interval的合并时比较常见的一类题目,网上的Amazon面经上也有面试这道题的记录。这里以LeetCode上的例题做练习。
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].
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
vector<Interval> merge(vector<Interval> &intervals) {
}
};
我的解法是新定义一个vector<Interval> res,然后每次从intervals中提一个Interval出来,如果这个Interval和res中已有的某个Interval有overlap,就合并成新的Interval,又放回intervals中。
循环终止条件是intervals.size() == 0。
class Solution {
public:
vector<Interval> merge(vector<Interval> &intervals) {
vector<Interval> res;
while(intervals.size() > ){
Interval inv = intervals.back();
intervals.pop_back();
vector<Interval>::iterator i = res.begin();
vector<Interval>::iterator rend = res.end();
for(; i < rend; ++i){
if(!((*i).start > inv.end || inv.start > (*i).end)){
(*i).start = min((*i).start, inv.start);
(*i).end = max((*i).end, inv.end);
intervals.push_back(*i);
res.erase(i);
break;
}
}
if(i == rend){ //事先将res.end()保存为rend很有必要,因为res.end()此时已经变化了。
res.push_back(inv);
}
}
return res;
}
};
AC 80ms
但上面的解法需要把一个Interval在两个vector间移来移去,而且每次从intervals取出后,又要从res的头部开始比较,比较费时间。最好当然是每次从intervals中取出一个Interval后,就将res中所有的都遍历完并合并。
这样的代码:
class Solution {
public:
vector<Interval> merge(vector<Interval> &intervals) {
vector<Interval> res;
if(intervals.size() == ) return res;
for(vector<Interval>::iterator it = intervals.begin(); it != intervals.end(); ++it){
Interval* interval = new Interval(it -> start, it -> end);
for(vector<Interval>::iterator it2 = res.begin(); it2 < res.end();){
if(!(interval -> end < it2 -> start || it2 -> end < interval -> start)){
interval -> start = min(interval->start, it2->start);
interval -> end = max(interval->end, it2->end);
it2 = res.erase(it2);
}else ++it2;
}
res.push_back(*interval);
}
return res;
}
};
AC 56ms
上面两种解法都是新定义一个vector用来存放结果。如果不新定义vector直接在原intervals上操作呢?这种解法参考了tenos的解法。
先将intervals按照start 升序排序,然后it1指向begin(),接着it2 指向it1的下一个元素,如果it2 和 it1有重叠,就把it2的区间算入 it1的区间,接着++it2,直到it2的区间和it1 没有重叠。
因为it2 走过的部分都已经被算入it1里,所以it1+1到当前it2的部分可以被删除了。
接着继续重复上述步骤,直到it1 或者 it2到达末尾。
这种解法要求 intervals 必须是有序的。
class Solution {
public:
vector<Interval> merge(vector<Interval> &intervals) {
if(intervals.size() <= ) return intervals;
sort(intervals.begin(), intervals.end(), compare);
vector<Interval>::iterator it1 = intervals.begin();
vector<Interval>::iterator it2 = it1 + ;
while(it1 != intervals.end() && it2 != intervals.end()){
if(!(it2 -> end < it1 -> start || it1 -> end < it2 -> start)){
it1 -> start = min(it1 -> start, it2 -> start);
it1 -> end = max(it1 -> end, it2 -> end);
++it2;
}else{
it1 = intervals.erase(it1 + , it2);
it2 = it1 + ;
}
}
if((it1+) != it2) intervals.erase(it1 + , it2);
return intervals;
}
private:
static bool compare(Interval a, Interval b){
return (a.start < b.start);
}
};
AC 60ms 因为在原vector上操作,所以比起解法二 略慢了一些。
基于Merge,会衍生出一些题目,比如下面的Insert。
Insert Interval
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
You may assume that the intervals were initially sorted according to their start times.
Example 1:
Given intervals [1,3],[6,9], insert and merge [2,5] in as [1,5],[6,9].
Example 2:
Given [1,2],[3,5],[6,7],[8,10],[12,16], insert and merge [4,9] in as [1,2],[3,10],[12,16].
This is because the new interval [4,9] overlaps with [3,5],[6,7],[8,10].
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
}
};
因为原vector 所包含的Interval是有序排列的,我们只要先将newInterval 放入 该放的地方,然后向后合并就可以。
class Solution {
public:
vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
vector<Interval>::iterator it1 = intervals.begin();
for(; it1 != intervals.end() && it1 -> end < newInterval.start; ++it1); //放入该放的地方
it1 = intervals.insert(it1, newInterval);
vector<Interval>::iterator it2 = it1 + ;
for(; it2 != intervals.end(); ++it2){
if(!(it2 -> end < it1 -> start || it1 -> end < it2 -> start)){
it1 -> start = min(it1-> start, it2 -> start);
it1 -> end = max(it1 -> end, it2 -> end);
}else break; //如果it2不再和it1重叠,因为intervals有序排列,所以it2后面的Interval肯定也不和it1重叠,可以退出循环了。
}
if(it2 != (it1 + )) intervals.erase(it1+, it2); //删除it2走过的部分。
return intervals;
}
};
总结:
通过这两题,(1) 首先我们需要熟练掌握一个基本的判断两个Interval是否overlap的方法: if(!((*i).start > inv.end || inv.start > (*i).end))
(2) 使用vector 的iterator方法遍历时,如果遍历的同时存在vector的大小更改,需要特别注意大小更改对 .end() 结果的影响,最好先将.end() 保存下来,除非你确实需要 .end()的动态变化作为比较值。
(3) 若在遍历vector时使用erase或者insert,因为vector大小被更改,因此原来的iterator会失效,需要将iterator 赋值为erase 和 insert 的返回值。
erase返回的值为删除当前 iterator 指向的元素后,下一个元素所在的地址。
insert返回的值为新增元素所在的地址(仅限于insert 一个元素的情况)。
[LeetCode] Merge Interval系列,题:Insert Interval,Merge Intervals的更多相关文章
- 【Leetcode】【Hard】Insert Interval
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...
- LeetCode第[21][23]题(Java):Merge Sorted Lists
题目:合并两个已排序链表 难度:Easy 题目内容: Merge two sorted linked lists and return it as a new list. The new list s ...
- 【题解】【区间】【二分查找】【Leetcode】Insert Interval & Merge Intervals
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...
- Leetcode: Merge/Insert Interval
题目 Given a collection of intervals, merge all overlapping intervals. For example,Given [1,3],[2,6],[ ...
- leetcode 56. Merge Intervals 、57. Insert Interval
56. Merge Intervals是一个无序的,需要将整体合并:57. Insert Interval是一个本身有序的且已经合并好的,需要将新的插入进这个已经合并好的然后合并成新的. 56. Me ...
- leetcode 57 Insert Interval & leetcode 1046 Last Stone Weight & leetcode 1047 Remove All Adjacent Duplicates in String & leetcode 56 Merge Interval
lc57 Insert Interval 仔细分析题目,发现我们只需要处理那些与插入interval重叠的interval即可,换句话说,那些end早于插入start以及start晚于插入end的in ...
- 【LeetCode】57. Insert Interval [Interval 系列]
LeetCode中,有很多关于一组interval的问题.大体可分为两类: 1.查看是否有区间重叠: 2.合并重叠区间; 3.插入新的区间: 4. 基于interval的其他问题 [ 做题通用的关键 ...
- 合并区间 · Merge Intervals & 插入区间 · Insert Interval
[抄题]: 给出若干闭合区间,合并所有重叠的部分. 给出的区间列表 => 合并后的区间列表: [ [ [1, 3], [1, 6], [2, 6], => [8, 10], [8, 10] ...
- 60. Insert Interval && Merge Intervals
Insert Interval Given a set of non-overlapping intervals, insert a new interval into the intervals ( ...
随机推荐
- Python中的赋值语法
Python中复制语法有6种 Basic Form >>>spam = 'spam' Tuple assignment >>>spam, ham = 'spam', ...
- 自测之Lesson14:多线程编程
题目:创建一个线程,并理清主线程结束时会发生什么. 代码: #include <stdio.h> #include <pthread.h> #include <unist ...
- Sail
DescriptionThe polar bears are going fishing. They plan to sail from (sx,?sy) to (ex,?ey). However, ...
- qwe
这次作业我负责的部分是把爬取完的聊天记录经行数据挖掘以及经行各种普通过滤高级过滤等. 运行截图如下: 数据分为四部分:账户名.qq/邮箱.包含关键词的发言次数.包含关键词的发言字数. 遇到的困难及解决 ...
- iOS开发Interface Builder技巧
1.使view的Size与view中的Content相适应:选中任意的一个view,然后Editor->Size to Fit Content,或者简单的按 ⌘=接着就会按照下面的规则对选中vi ...
- TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接
一.TCP连接的ISN 之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...
- 【week2】Scrum中的站立会议
Scrum站立会议 站立会议给我的第一印象就是站着开会,在经过我查阅资料之后,发现也是差不多的意思.学术一点的分析就是在Sprint开始后,团队将会在每个工作日特定时间举行一个简短会议,每次会议 ...
- 从1到n的阶乘的和(python)
今天在百度上逛一些ctf的平台,偶然发现一道编程题,于是乎,便用我刚刚学的python知识解了这道题 题目的描述是这样的: 计算1!+2!+3!+...+6666!后五位. 这个计算量很大啊,我还是用 ...
- zabbix概念
Zabbix是一个企业级的.开源的.分布式监控解决方案. Zabbix可以监控网络和服务的监控状况. Zabbix利用灵活的告警机制,允许用户对事件发送基于Email的告警. 这样可以保证快速的对问题 ...
- 【bzoj4165】矩阵 堆+STL-map
题目描述 定义和谐矩阵为长不小于 Mina 且宽不小于 Minb 的矩阵,矩阵的权值为整个矩阵内所有数的和.给定一个长为 N,宽为 M 的矩阵 A,求它的所有和谐子矩阵中权值第 K 小的矩阵,并输出它 ...