LeetCode 56 Merge Intervals--In C++

本文介绍了一种高效合并多个区间的方法,通过将区间的起点和终点转换为特定节点,并利用定制的排序策略对这些节点进行排序,从而实现快速区间合并。适用于解决如合并日程安排等问题。

思路:

主要想法是先从Intervals中取出所有的int值,封装到一个Node节点中,节点里保存了他是不是起点,与之匹配的值,和自己的值等3个信息。

然后对Node类型的数组workspace进行排序。

排序策略为:1.两个点值不相等,值小的排前面。2.两个点值相等,且一个为起点,一个为终点,则起点排前面。3.两个点值相等,且都为起点,终点大的排前面。4,两个点值相等,且都为终点,起点大的排前面。这个策略能适应所有的case。比如【1,4】【4,5】按照规则2,起点的4要排在终点4的前面,这个case的正确应返回【1,5】。

排序之后,从workspace的起点开始扫描,找到一个起点就记录下他的终点值,如果下步扫描又找到一个起点,就看看他的终点值比当前终点值大的话就更新当前终点值。直到workspace数组的扫描用角标所在位置的值和终点相等,则产生一个结果Interval,存入,等待返回。

举例:

Given [1,3],[2,6],[8,10],[15,18],
return [1,6],[8,10],[15,18].

则排序之后,找1的终点,为3.继续扫描,找到了2,而2只是一个起点,看看他的终点为6,比3要大,更新3为6.继续扫描找到了3,虽是一个终点但小于当前最大终点6,继续扫,找到了6,与当前最大终点重合了。说明一个组合被找到,建立【1,6】,准备返回。后面以此找到后续结果,返回。

这个方法时间复杂度为O(n),相当快。

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
 class Node{
public:
	int val;
	bool IsBegin;
	int maxend;//另一边界值 
	Node() :val(0), IsBegin(true),maxend(0){}
	Node(int val,bool IsBegin){
		this->val = val;
		this->IsBegin = IsBegin;
		maxend = 0;
	}

};
bool cmp(Node node1,Node node2){
	if (node1.val<node2.val){
		return true;
	}
	if (node1.val==node2.val){
		if (node1.IsBegin==true&&node2.IsBegin==false){//若起点和终点值相等,让起点排在前面
			return true;
		}
		if (node1.IsBegin == true && node2.IsBegin == true){
			if (node1.maxend>node2.maxend){
				return true;
			}
			else{
				return false;
			}
		}
		if (node1.IsBegin == false && node2.IsBegin == false){
			if (node1.maxend>node2.maxend){
				return true;
			}
			else{
				return false;
			}
		}
	}
	
	return false;
	
}

class Solution {
public:
    vector<Interval> merge(vector<Interval>& intervals) {
	vector<Interval> result;
	vector<Interval>::iterator it; 
	int k = intervals.size();
	Node* workspace = new Node [2*k];
	for (it = intervals.begin(); it != intervals.end();it++){
		Node* temp1 = new Node(it->start,true);
		workspace[distance(intervals.begin(), it)*2] = *temp1;//这里复制值后,存入workspace
		//cout << temp1->val<<endl;
		Node* temp2 = new Node(it->end,false);
		workspace[distance(intervals.begin(), it)*2+1] = *temp2;
		workspace[distance(intervals.begin(), it) * 2].maxend 
			= workspace[distance(intervals.begin(), it) * 2 + 1].val;
		workspace[distance(intervals.begin(), it) * 2+1].maxend
			= workspace[distance(intervals.begin(), it) * 2].val;
		//cout << temp2->val<<endl;
		delete temp1;
		delete temp2;
		
	}
	sort(workspace,workspace+2*k,cmp);
	/*for (int i = 0; i < 2 * k; i++){
		cout << workspace[i].val << endl;
	}*/
	int barr1 = workspace[0].val;
	int barr2 = workspace[0].maxend;
	//cout << barr2;
	for (int i = 0; i < 2 * k;i++){
		if (workspace[i].val==barr2 && workspace[i].IsBegin==false){
			//要确保有很多相等值时,barr2是一个最后一个终点
			if (i+1<2*k && workspace[i+1].val==barr2){
				continue;
			}
			Interval* re = new Interval(barr1,barr2);
			cout << barr1 << "," << barr2 << endl;
			result.push_back(*re);
			barr1 = workspace[i + 1].val;
			barr2 = workspace[i + 1].maxend;
			delete re;
			continue;
		}
		if (workspace[i].IsBegin==true){
			int temp = workspace[i].maxend;
			if (temp>barr2){
				barr2 = temp;
			}
		}
	}

	return result;
}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值