题目:
There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it's horizontal, y-coordinates don't matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons.
An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.
Example:
Input: [[10,16], [2,8], [1,6], [7,12]] Output: 2 Explanation: One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).
题目大意:
在二维空间中有许多的圆形气球。对于每个气球,给出了该气球的在横坐标上的起始位置和终止位置,而且起始位置始终小于终止位置。现在开始射箭,箭可以在横坐标不同点上垂直向上发射。如果箭的起始点为x,如果x在气球的起始位置和终止位置之间,那么气球就会爆炸。现在有不限数量的箭可以发射。假设一直箭每次可以向上发射到无穷远处。现在的问题是,求出可以让所有气球爆炸的最少箭数。
这道题是典型的用贪婪算法来做的题,因为局部最优解就等于全局最优解,我们首先给区间排序,我们不用特意去写排序比较函数,因为默认的对于pair的排序,就是按第一个数字升序排列,如果第一个数字相同,那么按第二个数字升序排列,这个就是我们需要的顺序,所以直接用即可。然后我们将res初始化为1,因为气球数量不为0,所以需要先射出一支,然后这一箭能覆盖的最远位置就是第一个气球的结束点,用变量end来表示。然后我们开始遍历剩下的气球,如果当前气球的开始点小于等于end,说明跟之前的气球有重合,之前那一箭也可以照顾到当前的气球,此时我们要更新end的位置,end更新为两个气球结束点之间较小的那个,这也是当前气球和之前气球的重合点,然后继续看后面的气球;如果某个气球的起始点大于end了,说明前面的箭无法覆盖到当前的气球,那么就得再射出一支,既然又射出去了一支,那么我们此时就要把end设为当前气球的结束点了,这样贪婪算法遍历结束后就能得到最少的箭数了。
代码如下:
class Solution {
public:
int findMinArrowShots(vector<pair<int, int>>& points) {
if (points.empty()) return 0;
sort(points.begin(), points.end());
int res = 1, end = points[0].second;
for (int i = 1; i < points.size(); ++i) {
if (points[i].first <= end) {
end = min(end, points[i].second);
} else {
++res;
end = points[i].second;
}
}
return res;
}
};