LeetCode 56

    这个题的意思是:给定一组"区间",将所有能够合并的区间合并,返回最终的区间的集合。

说实话拿到这个题的时候多么希望这些区间是有序的(就是所有区间按照起始大小排好序了),为此我强行将它当作有序的,还写了代码进行提交,然而结果是题目给出了 "[[2,3],[4,5],[6,7],[8,9],[1,10]]" 这样的测试用例。好吧,说明这些区间是无序的,这下难度增加了很多,说实话解题的思路我一时真的没想到,想的快要放弃了,曾想看看别的代码,但是还是忍住了。经过今早一番的思索,终于找到了解题思路,所以要分享出来:

  我的思路是:取出集合(tmp)的第一个区间[s,e],然后从后面的区间中找能够融合的区间,若可以融合则去掉这个被融合的区间(此时[s,e]可能会扩大),若是不能融合的话先将它放到一个额外空间中(额外空间_swap),最后将将额外空间的元素代替原始空间中的元素(tmp=_swap,这样就去掉了那些被融合的元素),然后再依次遍历tmp,直到最后tmp中只剩一个元素了,此时问题就解决了。

    其中每遍历完一趟后,我们需要作个决策:就是当前区间能不能直接当作最终问题的解集(ret)的一个元素(若是的话就将它加入的问题最终的解的集合(ret)中),那么怎样判断他是独立的呢(意思它不能再跟任何区间融合了),我是这样解决的:

    每趟遍历开始的时候我设置一个 bool 值(bool flag=false),在遍历的过程中,若区间被融合了则把它设置为true(说明区间[s,e]被扩大了,被扩大的区间很有可能与之前被过滤的区间再次融合,所以我们不能直接将它加入到问题的最终的解集(ret)中),举个例子说明一下吧:

    若区间集合为:"[[2,3],[4,9],[3,6],[11,15]] " 

 1.我们首先选择的区间是[2,3]

 2.往后遍历的过程中,区间[4,9]会被过滤掉(被添加到_swap中去了,因为它无法和[2,3]融合),但是在后面遇到区间 [3,6] 的时候,区间[2,3]被融合成了[2,6],这个时候[2,6]是不能被添加到问题的最终得解集(ret)中的,因为之前错过了区间[4,9],所以应该将它继续添加到_swap中(这个时候flag是被置为ture的,因为区间[2,3]发生了融合),这样下次[4,9]与[2,6]就能够融合了。

 3.若是遍历完一趟后,flag仍然为flas,则说明该区间不会融合了,所以应该将它直接加入到问题最终的解集(ret)中

 4.遍历到tmp只剩一个元素的时候,直接将这个元素加入到ret中即可.


我相信我说明白了这个问题了,下面给上代码吧:

/**
 * 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 Solution {
public:
    vector<Interval> merge(vector<Interval>& intervals) 
    {  
		vector<Interval> ret;
		vector<Interval> tmp = intervals; //这样主要是为了不改变intervals的值
		vector<Interval> _swap;           //保留区
		
		while (tmp.size() > 1)
		{
			bool flag = false;
			_swap.clear();
			int pos = 0;
			int next = pos + 1;
			int tail = tmp.size();
			int s = tmp[pos].start;
			int e = tmp[pos].end;
			while (next < tail)
			{
				if (tmp[next].end >= s && tmp[next].start <= e)
				{ //该条件满足了,说明[s,e]可能得到了延伸,tmp[next]元素被融合了,应该去掉了
					flag = true;
					e = max(e, tmp[next].end);
					s = min(s, tmp[next].start);
				}
				else 
				{ //不能融合的先留下
					_swap.push_back(tmp[next]);
				}
				++next;
			}
			
			//将留下的继续融合
			tmp.clear();
			tmp = _swap;
			
			if (!flag)
			{ //此时说明了[s,e]区间中不会再有重叠的部分了,也就是说它是独立的
				ret.push_back(Interval(s, e));
			}
			else
			{ // 说明[s,e]区间延伸了,无法预测他是否还可以与其他部分融合,所以它很可能再和其他的融合
				tmp.push_back(Interval(s, e));
			}			
		}

		if (tmp.size() == 1)
		{
			ret.push_back(tmp[0]);
		}
		return ret;
	}
};

程序的结果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值