一、概述
輸入一個元素爲子區間的長序列和一個目標區間,將目標區間插入到長序列中。注意長序列中各元素不重疊,要求插入後不破壞不重疊這一性質。舉例如下:
長序列爲[[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;
}
};
三、總結
雙指針法一直是很好用的方法。