Leetcode-Algorithm-Greedy-452
-
题目:
-
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.
(有一些球形的气球分布在一个二维的平面上,每个气球我们给定它在 x 轴上的坐标,因为箭是从x 轴的点上沿 y 轴方向垂直射出的,因此气球的y 坐标可以忽略。若箭是从点 x 射出,气球的横向坐标为Xstart , Xend ,当 Xstart<=x<=Xend 时就可以将气球打爆。由于气球的横坐标有可能重叠,因此最少可以用多少支箭将所有的气球打爆。)
例子:
输入:[[10,16], [2,8], [1,6], [7,12]]
输出:2
(也就是说,最少用2支箭就可以将这些坐标表示的气球全部打爆。)
题解:
方法:(贪心算法)
如果用最少数量的箭将所有的气球打爆,那么每射出一支箭,就要打爆尽可能多的气球。因为只有当气球有重叠的时候才能同时打爆,因此问题成为找到尽可能多的气球,它们在
x
轴的某一点上重叠,这样用一支箭就能把气球都打爆,剩下的气球用同样的方式继续,直到所有气球的打爆了。
class Solution {
public:
int findMinArrowShots(vector<pair<int, int>>& points) {
if (points.empty()) return 0;
//记录所有的气球的位置,若起始位置相同,看成是同一个气球
multimap<int, int> balloons;
for (auto point : points)
balloons.insert(point);
int ballNum = balloons.size();
int arrowNum = 0;
vector<int> burst;
while (ballNum > 0) {
map<int, int>::iterator iter = balloons.begin();
int start = iter->first;
int end = iter->second;
burst.push_back(start);
//找到一支箭可以打爆的尽可能多的气球。
while (++iter != balloons.end()) {
if (iter->first > end)
break;
burst.push_back(iter->first);
start = iter->first;
end = (iter->second > end ? end : iter->second);
}
//气球打爆了,在列表中去掉。
ballNum -= burst.size();
for (int i = 0; i < burst.size(); ++i)
balloons.erase(burst[i]);
burst.clear();
++arrowNum;
}
return arrowNum;
}
};
分析:
由于算法开始的时候,用一个multimap来重新存储气球的坐标,目的是为了将给定的气球坐标排好序,好让箭能从坐标