贪心算法中的区间调度问题

一、问题概述

经典问题,给出形如 [ begin,end ]的闭区间,设计一个算法,求出这些区间中最多有几个互不相交的区间。

比如说,这四个区间,[1,2], [2,3], [3,4], [1,3],最多有三个互不相交,区间边界相交并不算重叠。那么这个问题是可以用贪心来解决的,

这个问题看起来可以用几个贪心策略解决,但都是有问题的。比如说我们可以按照开始时间排序,但是可能存在某些区间开始很早,但是很长,使得我们错误地错过了一些短的区间。

如果选择间隔最小的区间,则可能出现该区间相交的区间很多导致答案错误。

那么我们换一个思路想,假设一个人一天有很多活动,那么去参加那些结束时间早的,人一天的自由时间会更多,则可以参加的活动越多。

贪心策略就是: 对区间的右边界排序,选取结束时间最早的,然后删除与该区间重叠的区间,重复上述步骤。

不难发现排序之后,如果与该区间重叠,则必然begin小于选择的区间的end。

class Solution {
    
    
public:
	int get_solution(vector<vector<int>> & intervals)
	{
    
    
		if (intervals.size() == 0)return 0;
		sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v)
			{
    
    
				return u[1] < v[1];
			}); 
		int right = intervals[0][1];//初始右边界
		int res = 1;
		int size = intervals.size();
		for (int i = 1; i < size; i++)
		{
    
    
			if (intervals[i][0] >= right)
			{
    
    //左边界大于右边界
				right = intervals[i][1];
				res++;
			}
		}
		return res;
	}
};

二、例题

leetcode435. 无重叠区间

题目地址

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

很简单,我们反过来找最多互不相交的区间数量,减去即可。

class Solution {
    
    
public:
	int eraseOverlapIntervals(vector<vector<int>>& intervals) {
    
    
		if (!intervals.size())return 0;
		sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v)
			{
    
    
				return u[1] < v[1];
			});
		int right = intervals[0][1];
		int res = 1;
		for (int i=1;i<intervals.size();i++)
		{
    
    
			if (intervals[i][0] >= right)
			{
    
    
				res++;
				right = intervals[i][1];
			}
		}
		return intervals.size()-res;
	}
};

leetcode452. 用最少数量的箭引爆气球

题目链接

扫描二维码关注公众号,回复: 12572998 查看本文章

一支弓箭可以沿着 x 轴从不同点完全垂直地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 start,end, 且满足 start ≤ x ≤ end,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。

考虑所有气球中右边界位置最靠左的那一个,那么一定有一支箭的射出位置就是它的右边界(否则就没有箭可以将其引爆了)。当我们确定了一支箭之后,我们就可以将这支箭引爆的所有气球移除,并从剩下未被引爆的气球中,再选择右边界位置最靠左的那一个,确定下一支箭,直到所有的气球都被引爆。

class Solution {
    
    
public:
	int findMinArrowShots(vector<vector<int>>& points) 
	{
    
    
		if (points.size() == 0)return 0;
		sort(points.begin(), points.end(), [](const vector<int>& a, const vector<int >& b)
			{
    
    return a[1] < b[1];});
		int pos = points[0][1];
		int res = 1;
		for (auto &t : points)
		{
    
    
			if (pos < t[0])
			{
    
    
				pos = t[1];
				res++;
			}
		}
		return res;
	}
};

猜你喜欢

转载自blog.csdn.net/weixin_45605341/article/details/112967991