题目介绍:已知在一个平面上有一定数量的气球,平面可以看作一个坐标系,在平面的x轴的不同位置安排弓箭手向y轴方向射箭,弓箭可以向y轴走无穷远;给定气球的宽度xstart<=x<=xend,问至少需要多少弓箭手,将全部气球打爆?
例如:[[10,16],[2,8],[1,6],[7,12]],至少需要2个弓箭手。
分析:
- 对于某个气球,至少需要使用1只弓箭将它击穿。
- 对这只气球击穿的同时,尽可能击穿其他更多的气球(贪心思想)。
算法思路:
- 对各个气球进行排序,按照气球的左端点从小到大排序。
- 遍历气球数组,同时维护一个射击区间,在满足可以将当前气球击穿的前提下,尽可能击穿更多的气球,每击穿一个新的气球,更新一次射击区间(保证射击区间可以将新气球也击穿)。
- 如果新的气球无法被击穿,则需要增加一名弓箭手,即维护一个新的射击区间(将该气球击穿),随后继续遍历数组。
代码(c++):
#include <vector>
#include <algorithm>
bool cmp(const std::pair<int, int> &a, const std::pair<int, int> &b){
return a.first<b.first;
}
class Solution {
public:
int findMinArrowShots(std::vector<std::pair<int, int>>& points) {
if (points.size()==0){
return 0;
}
std::sort(points.begin(), points.end(), cmp);
int shoot_num = 1;
int shoot_begin = points[0].first;
int shoot_end = points[0].second;
for (int i=1; i<points.size(); i++){
if (points[i].first<=shoot_end){
shoot_begin=points[i].first;
if (shoot_end > points[i].second){
shoot_end=points[i].second;
}
}
else{
shoot_num++;
shoot_begin=points[i].first;
shoot_end=points[i].second;
}
}
return shoot_num;
}
};