LeetCode 合并区间

这篇博客探讨了LeetCode中的合并区间问题,通过排序和优化代码来提高效率。作者首先分析了判断区间重叠的条件,并指出通过排序可以简化情况。然后,通过示例图解展示了算法过程,指出原始代码的不足之处在于erase操作导致的时间消耗。最后,提出了使用新容器优化的解决方案,以降低复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

思路分析: 此题的难点就是判断哪些区间重叠了,以及如何进行合并。重叠只有两种情况,一个区间是另外一个区间的子集,或者两个区间相邻(有部分重叠)。由于有区间在容器中有次序关系,那么需要分a是b的子集还是b是a的子集,则重叠的情况就分为了四种。那能不能找到一种操作,在合并之前就将所有的情况合并为一种情况呢?答案显然是有的——排序。此处的排序需要以左区间为主次序递增,右区间为辅次序递增。即首先保证左区间递增,如果某两个元素的左区间相同,那么则比较他们的右区间。排序后再进行合并即可。
示例图解
在这里插入图片描述

/**
* 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:
	static bool myCompare(Interval one, Interval two){
		//以start为主次序递增
		if (one.start == two.start){//当start相等的时候,才进行比较end
			return one.end < two.start;
		}
		else {//否则直接比较start的大小关系
			return one.start < two.start;
		}
	}

	vector<Interval> merge(vector<Interval>& intervals) {
		sort(intervals.begin(), intervals.end(), myCompare);//按照自定义顺序进行排序
		for (int i = 0; i < intervals.size(); ++i){//动态扫描
			int begin = intervals[i].start;//基准begin
			int end = intervals[i].end;//基准end
			//因为排序的时候就保证了start为主次序递增,只要下一个的start小于上一个的end,就证明可以进行合并
			while (i + 1 < intervals.size() && intervals[i + 1].start <= end){//如果能进行合并
				end = max(intervals[i + 1].end, end);//更新
				intervals.erase(intervals.begin() + i + 1);
			}
			intervals[i].end = end;//更新i的end
		}
		return intervals;
	}
};

在这里插入图片描述
虽然通过了,但是实在是太慢了!
接下来我们想想如何优化代码。
优化思路:不难发现,此算法最为消耗时间的莫过于intervals.erase(intervals.begin() + i + 1);因为vector容器是非链式容器,在随机访问上快速,在删除上比较慢。而且此算法是在给定的参数上进行修改合并,我们可以新建一个容器进行存放结果,从而降低复杂度。
(可以自己先实现优化后的代码,再来比较一下谁的代码更精简。)

/**
* 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:
	static bool myCompare(Interval one, Interval two){
		//以start为主次序递增
		if (one.start == two.start){//当start相等的时候,才进行比较end
			return one.end < two.start;
		}
		else {//否则直接比较start的大小关系
			return one.start < two.start;
		}
	}

	vector<Interval> merge(vector<Interval>& intervals) {
		vector<Interval> result;
		int vecSize = intervals.size();
		sort(intervals.begin(), intervals.end(), myCompare);//按照自定义顺序进行排序
		for (int i = 0; i < vecSize; ++i){//扫描
			int begin = intervals[i].start;//基准begin
			int end = intervals[i].end;//基准end
			//因为排序的时候就保证了start为主次序递增,只要下一个的start小于上一个的end,就证明可以进行合并
			while (i + 1 < vecSize && intervals[i + 1].start <= end){//如果能进行合并
				++i;
				end = max(intervals[i].end, end);//更新end(合并区间)
			}
			result.push_back(Interval(begin, end));
		}
		return result;
	}
};

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值