您的位置:首页 > 其它

57. Insert Interval

2015-07-29 14:44 239 查看
此题有两种思路。一种思路为:先按照start值在原数组中二分查找待插入的区间,假设查找到的位置为ite,从ite或者ite-1开始合并区间直到不能合并为止(终止条件是合并后区间的end<当前区间的start),然后在原数组中删除参与合并的区间,再插入合并后的新区间。

在原始数组上进行操作的代码如下:

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]开始往后合并,合并完成后,再检查对头及队尾,需要的话,再合并一次即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: