57. Insert Interval
2015-07-29 14:44
239 查看
此题有两种思路。一种思路为:先按照start值在原数组中二分查找待插入的区间,假设查找到的位置为ite,从ite或者ite-1开始合并区间直到不能合并为止(终止条件是合并后区间的end<当前区间的start),然后在原数组中删除参与合并的区间,再插入合并后的新区间。
在原始数组上进行操作的代码如下:
在新数组上保存结果的代码如下:
代码如下所示:
此题需要注意的一点trick是当需要合并区间时,我们动态改变newInterval的起点和结尾,这样会让逻辑更加清晰。另外以前换组的时候,面过这道题,但是出题的人,添加了一个附属条件,这些interval是在一个圆环上。比如当环是[1, 255]时,如果两个Interval分别是[1,234], [222,
4], Merge最后的结果是[1,4]。这个条件完全是个干扰,因为如果真的在逻辑中考虑环的话,非常麻烦,而且在环上做循环合并的话,无法判断何时该终止循环。当时我的解法就是,如果第一个是跨越0点的话(比如[234,7]),把它拆分成两个interval([234, 255],[1,7]), 然后把[1,7]插到队头,[234,255]插到队尾。 从[1,7]开始往后合并,合并完成后,再检查对头及队尾,需要的话,再合并一次即可。
在原始数组上进行操作的代码如下:
class Solution { private: static bool comp(Interval a, Interval b) { return a.start < b.start; } public: vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) { //在原始数组上进行操作 vector<Interval>::iterator ite = lower_bound(intervals.begin(),intervals.end(), newInterval, comp);//按照start值二分查找 if(ite != intervals.begin() && newInterval.start <= (ite-1)->end)//ite的上一个区间也可能参与合并 { ite--; //ite->start一定小于等于newInterval.start,因为数组按区间起点有序 newInterval.start = ite->start; } vector<Interval>::iterator eraseBegin = ite; for(; ite != intervals.end() && newInterval.end >= ite->start; ite++) if(newInterval.end < ite->end)newInterval.end = ite->end;//合并后的新区间存放于newInterval ite = intervals.erase(eraseBegin, ite);//[eraseBegin, ite)是合并时应该删掉的区间 intervals.insert(ite, newInterval);//插入合并后的区间 return intervals; } };
在新数组上保存结果的代码如下:
class Solution { private: static bool comp(Interval a, Interval b) { return a.start < b.start; } public: vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) { vector<Interval> res; res.reserve(intervals.size()); int i; //插入前部分不需要合并的区间 for(i = 0; i < intervals.size() && intervals[i].end < newInterval.start; i++) res.push_back(intervals[i]); //i为需要合并的起点,注意的是合并后新区间的起点只和第一个合并的区间有关,因为数是时按区间起点有序的 if(i < intervals.size())newInterval.start = min(newInterval.start, intervals[i].start); //合并区间 for(; i < intervals.size() && newInterval.end >= intervals[i].start; i++) if(newInterval.end < intervals[i].end)newInterval.end = intervals[i].end; //插入合并后的区间 res.push_back(newInterval); //插入剩余的区间 res.insert(res.end(), intervals.begin()+i, intervals.end()); return res; } };另外一种思路是遍历数组,如果当前interval在newInterval后面,则将当前interval插入结果中;如果当前interval在newInterval前面,则将newInterval插入结果并把newInterval赋值为当前interval;如果两者重叠,则合并两个区间,修改newInterval的数值,这三种情形如下图所示。图中的Current对应newInterval,New对应intervals[i]。
代码如下所示:
class Solution { public: vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) { vector<Interval> res; for(int i=0; i<(int)intervals.size(); i++) if(intervals[i].end < newInterval.start){ res.push_back(intervals[i]); }else if(intervals[i].start > newInterval.end){ res.push_back(newInterval); newInterval = intervals[i]; }else { newInterval.start = min(newInterval.start, intervals[i].start); newInterval.end = max(newInterval.end, intervals[i].end); } res.push_back(newInterval); return res; } };
此题需要注意的一点trick是当需要合并区间时,我们动态改变newInterval的起点和结尾,这样会让逻辑更加清晰。另外以前换组的时候,面过这道题,但是出题的人,添加了一个附属条件,这些interval是在一个圆环上。比如当环是[1, 255]时,如果两个Interval分别是[1,234], [222,
4], Merge最后的结果是[1,4]。这个条件完全是个干扰,因为如果真的在逻辑中考虑环的话,非常麻烦,而且在环上做循环合并的话,无法判断何时该终止循环。当时我的解法就是,如果第一个是跨越0点的话(比如[234,7]),把它拆分成两个interval([234, 255],[1,7]), 然后把[1,7]插到队头,[234,255]插到队尾。 从[1,7]开始往后合并,合并完成后,再检查对头及队尾,需要的话,再合并一次即可。
相关文章推荐
- iPhone应用程序开发基础之一: IBOutlet与IBAction
- 自动化测试总结
- android+Python socket
- DataProvider不等于SQLHelper
- 什么是流媒体技术
- objectARX错误处理函数
- Redis 和 Jedis
- FMDBModel使你的实体类具备直接操作数据库的功能
- zoj 2112 Dynamic Rankings (动态主席树)
- 判断decimal 是否为整数
- css3鼠标状态
- 查看 python安装目录
- javascript字符串函数
- UVA 10976 - Fractions Again?!
- CMD网络命令
- 流媒体与视频监控开发相关博客文章系列收集
- AOP面向方面编程
- iOS开发多线程篇—GCD的基本使用
- 使用Eclipse构建Maven项目
- 软件开发生命周期的管理