一、概述
输入一个元素为子区间的长序列和一个目标区间,将目标区间插入到长序列中。注意长序列中各元素不重叠,要求插入后不破坏不重叠这一性质。举例如下:
长序列为[[1,2],[3,5],[6,7],[8,10],[12,16]],目标区间为[4,8],要求不重叠,则插入后的长序列为[[1,2],[3,10],[12,16]]。
这道题与第56题相关,最简单的做法是把目标序列push进长序列,然后sort,化为56题做。但是很麻烦,时间复杂度O(nlogn)。我的方法时间复杂度为O(n)。
二、分析
题目很直观,总的来说就是在子区间中找到目标区间左端点left和右端点right的位置,我们维护两个变量now_min和now_max记录位置:
先找左端点的位置:
从头开始遍历整个序列,找到第一个子区间n,它的右端点值大于等于left,则left位置一定在n-1的右端点到n的右端点这部分区间内,即now_min可能取值为n的左端点,此时n的左端点值小于left;或取值为left,此时n的左端点值大于left。
然后找右端点的位置:
右端点可能落在子区间之内,也可以落在子区间之间,因此都需要注意:以n为第一个区间,以n的右端点到n+1的左端点为第二个区间;以此类推。在具体实现时,首先判断第i个区间,然后判断第i个区间和第i+1个区间之间的区间。当right落在区间内时,now_max取值为区间右端点;当right落在区间之间时,now_max取值为right。
当now_min和now_max取值完毕,push到res中,之后使用insert将原序列后面的元素插入res的后面即可。
代码如下:
class Solution {
public:
vector<vector<int>> insert(vector<vector<int>>& inter, vector<int>& newInter) {
vector<vector<int>> res;
if(inter.size()==0)
{
res.push_back(newInter);
return res;
}
for(int i=0;i<inter.size();++i)
{
if(inter[i][1]<newInter[0])
{
res.push_back(inter[i]);
}
else
{
int now_min=-1;
if(inter[i][0]<newInter[0])
now_min=inter[i][0];
else
now_min=newInter[0];
int now_max=-1;
if(inter[i][0]>newInter[1])
now_max=newInter[1];
else
{
for(;i<inter.size();++i)
{
if(inter[i][0]<=newInter[1]&&inter[i][1]>=newInter[1])
{
now_max=inter[i][1];
break;
}
if(i==inter.size()-1||(inter[i][1]<=newInter[1]&&inter[i+1][0]>newInter[1]))
{
now_max=newInter[1];
break;
}
}
++i;
}
vector<int> tmp;
tmp.push_back(now_min);
tmp.push_back(now_max);
res.push_back(tmp);
res.insert(res.end(),inter.begin()+i,inter.end());
return res;
}
}
res.push_back(newInter);
return res;
}
};
三、总结
双指针法一直是很好用的方法。