题目描述
在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。
一支弓箭可以沿着 x 轴从不同点完全垂直地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。
给你一个数组 points ,其中 points [i] = [xstart,xend] ,返回引爆所有气球所必须射出的最小弓箭数。
解题思路
贪心算法
解题时,我们可以贪心地选择发射的位置,总是考虑,是否可以在下一个单位的x坐标发射而不漏掉气球。这样,我们能确定,我们引爆了所有的气球并且争取到了最小的弓箭数。
考虑发射位置:我们明白,发射位置一定在某一些气球的右边缘。
是否所有的气球的右边缘都要有一支弓箭射出呢?并不是如此,因此,我们还需要考虑,当我们遇到了一个气球的右边缘,我们是否必要去发射一支弓箭。
确定的方法是:观察这个气球的左边缘,看它的位置是否在上一只发射的弓箭只后,如果在后面,就意味着它在之前没有被引爆;如果在前面或恰好在那个位置,就意味着它已经被上一只弓箭(或者更早的)引爆了,不需要我们再次发射弓箭了。
在上述思想下,我们只需要对输入的区间按右端大小进行排序。遍历、依次验证是否需要在该处发射弓箭,计算发射总数量即可得到答案。
代码
bool comp(vector<int>a,vector<int>b)
{
return a[1]<b[1];
}
class Solution
{
public:
int findMinArrowShots(vector<vector<int>> points)
{
if(points.empty())
{
return 0;
}
sort(points.begin(), points.end(), comp);
int res(0);
int idx(0);
int last(INT_MIN);
while(idx<points.size())
{
if(points[idx][0]>last||points[idx][0]==INT_MIN)//考虑int的边界条件
{
res++;
last = points[idx][1];;
}
idx++;
}
return res;
}
};