拿到题目,一看,对于两个interval分类讨论,一共三种情况,部分包含,全部包含,不包含,然后写个逻辑区分这三种情况
显然需要先排序,排序的目的是当前的和后面一个合并,不需要再考虑前面的interval. 但是是start 还是end呢?最大兼容活动子集问题用的是end排序,这里我也优先考虑这个,但是发现会出问题,例如[1,3] [4, 6] [2,9] 这样的话12区间不并,23并但是还要和1并这就不行了,因此尝试start
进行简短的证明:
按照start 排序, [satrt1,end1] satrt2,end2] satrt3,end3] 可以得到start2<start3,由于end1<start2 因此end1< start3, 主要是 2 3 merge之后[start2,end3] 一定与1 不能merge
按照end 排序 [satrt1,end1] satrt2,end2] satrt3,end3] 可以得到end1<sart2<end2<end3, 然而2,3合并结果可能是[start3,end3] 可能出现start3<end1的情况,因此不能保证与1不merge。
因此选择start排序,可以从前到后i遍历,不考虑 i-1是否需要merge
判断逻辑其实分3种:
1. s1.begin s2.begin s1.end, s2.end 或者switch s1 s2
2 s1.begin s2,begin s2.end s1.end 或者switch s1 s2
3. s1.begin s1.end s2.begin s2.end 或者switch s1 s2
然后里面出现merge,删除两个,插入并好的一个优点纠结,一开始以为start倒序 可以 全用push_back pop_back 但是 后面发现还是不行,因为后面还是有中间的删除,于是暂时用 vector 中间删,中间差来实现, insert erase 参数要用iterator
附上代码,还没过,编译不过,不认识带compare的sort函数= =我用gcc 3.2.3和 4.5.4都过了,gcc 4.7.3 居然和我说不过编译。。。。(问题出在SortComp要是static,leetcode系统维护人员这么做,好吧,问题都出在我这里,我忘记测试环境是面向对象的代码,于是乎class内部的函数写成静态表示不属于某个对象,而是属于这个class的 )
bool SortComp(const Interval& T1, const Interval&T2)
{
return T1.start<T2.start;
}
bool ShouldMerge(Interval& n1,Interval& n2, Interval& mergedn)
{
if(n1.start<=n2.start&&n2.start<=n1.end&&n1.end<=n2.end)//intersect
{
mergedn.start=n1.start;
mergedn.end=n2.end;
return true;
}
if(n1.start<=n2.start&&n2.end<=n1.end)//subset of another
{
mergedn.start=n1.start;
mergedn.end=n1.end;
return true;
}
return false;
}
vector<Interval> merge(vector<Interval> &intervals)
{
sort(intervals.begin(),intervals.end(),SortComp);//start sort ascending
for(int i=0;i<intervals.size()-1;i++)
{
Interval mergedn;
if(ShouldMerge(intervals.at(i),intervals.at(i+1),mergedn)|| ShouldMerge(intervals.at(i+1),intervals.at(i),mergedn))
{
intervals.erase(intervals.begin()+i);
intervals.erase(intervals.begin()+i);
intervals.insert(intervals.begin()+i,mergedn);
i--;
}
else
;
}
return intervals;
}
PS:这是一道4* 的题目,应该有一番斗争了,担心时间效率不过。事实确实这么做vector大量移动元素,超时了,
Last executed input: | [[74,78],[61,63],[46,50],[51,54],[50,50],[60,64],[39,42],[25,27],[91,95],[14,16],[85,85],[5,7],[45,46],[45,49],[66,66],[73,73],[25,26],[25,26],[45,48],[67,67],[63,65],[82,84],[90,92],[47,49],[3,4],[1,5],[64,66],[73,77],[90,94],[20,21],[84,87],[48,49],[80,80],[85,85],[53,55],[21,23],[31,34],[71,75],[62,65],[8,9],[32,33],[7,8],[20,22],[57,57],[51,53],[18,21],[71,75],[49,50],[44,45],[28,31],[38,42],[15,17],[4,7],[48,52],[9,10],[37,38],[69,70],[89,89],[28,29],[52,52],[75,76],[20,21],[90,94],[49,53],[56,59],[84,85],[79,83],[20,21],[90,93],[55,59] |
昨天发现自己操作vector merge时犯了严重错误,几乎时操作次数double,本来合并两个,不需要删除两个元素,再插入合并的元素,只需删除第一个,然后替换第二个就可以了。出现这一问题,主要是一开始没有把整个大的逻辑框图设计好,而过早设计细节,就和读论文一样,先看大标题,摘要,结论,有个bird view, 然后再细节,设计复杂程序尤其如此,先写大的框架,不要先把实现细节写完,否则后面的大框架都没想清楚,所以但是细节是否能实现做到心中有数。所以前面写的不拘泥于细节的伪代码很有用的
小优化后,还是超时了,操作次数最多 n-1 +n-2....+1 =O(n^2) 可见需要更优的
想到一个刮三的算法,先copy到linklist,利用它的高效插入删除,然后再copy回vector, 时复O(n) 空复O(n) 可以尝试下
果然就过了,这次写linklist比较顺手一些,因为以前写经常会某些case指针就挂掉了,所以每次访问next都想清楚就OK了,看来链表在多次插入删除时效率极高,而且他还容忍我新建一个struct~~~
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
struct Node
{
Interval interval;
Node* next;
};
class Solution {
public:
static bool SortComp(const Interval& T1, const Interval&T2)
{
return T1.start<T2.start;
}
Node* CreateLinkList(vector<Interval> data)
{
Node* head=NULL;
head=new Node();
head->interval=data[0];
head->next=NULL;
Node* rail=head,*p;// record each rail
for(int i=1;i<data.size();i++)
{
p=new Node();
p->interval=data[i];
p->next=NULL;
rail->next=p;
rail=rail->next;
}
return head;
}
bool ShouldMerge(Interval n1,Interval n2, Interval& mergedn)
{
if(n1.start<=n2.start&&n2.start<=n1.end&&n1.end<=n2.end)//intersect
{
mergedn.start=n1.start;
mergedn.end=n2.end;
return true;
}
if(n1.start<=n2.start&&n2.end<=n1.end)//subset of another
{
mergedn.start=n1.start;
mergedn.end=n1.end;
return true;
}
return false;
}
vector<Interval> merge(vector<Interval> &intervals)
{
if(intervals.size()<=1) return intervals;
sort(intervals.begin(),intervals.end(),SortComp);//start sort descending, for vector pop_back
Node* head=CreateLinkList(intervals);
//merge interval with linklist
Node* p=head;
while(p->next!=NULL)//at least two node initially
{
Interval mergedn;
if( ShouldMerge(p->interval,p->next->interval,mergedn) || ShouldMerge(p->next->interval,p->interval,mergedn) )
{
//delete p, p->next;
//insert mergedn;
p->interval=mergedn;
p->next=p->next->next;
}
else
p=p->next;
}
/*
for(int i=0;i<intervals.size()-1;i++)
{
Interval mergedn;
if(ShouldMerge(intervals.at(i),intervals.at(i+1),mergedn)|| ShouldMerge(intervals.at(i+1),intervals.at(i),mergedn))
{
intervals.erase(intervals.begin()+i);
intervals.at(i)=mergedn;
//intervals.erase(intervals.begin()+i);
//intervals.insert(intervals.begin()+i,mergedn);
i--;
}
else
;
}*/
//copy linklist to vector
p=head;
intervals.clear();
while(p!=NULL)
{
intervals.push_back(p->interval);
p=p->next;
}
return intervals;
}
};