这是为什么?我们考虑任意一种最优的方法,对于其中的任意一支箭,我们都通过上面描述的方法,将这支箭的位置移动到它对应的「原本引爆的气球中最靠左的右边界位置」,那么这些原本引爆的气球仍然被引爆。这样一来,所有的气球仍然都会被引爆,并且每一支箭的射出位置都恰好位于某一个气球的右边界了。
有了这样一个有用的断定,我们就可以快速得到一种最优的方法了。考虑所有气球中右边界位置最靠左的那一个,那么一定有一支箭的射出位置就是它的右边界(否则就没有箭可以将其引爆了)。当我们确定了一支箭之后,我们就可以将这支箭引爆的所有气球移除,并从剩下未被引爆的气球中,再选择右边界位置最靠左的那一个,确定下一支箭,直到所有的气球都被引爆。)
按左端右端排序都是一样的,都是寻求最小交集区间。[0,9]和[0,6]交集[0,6],所以[0,6]上可以一箭射穿,[0,6]和[7,8]没有交集,所以箭数+1
题目等价: 求交集的合并区间
class Solution {
public:
int findMinArrowShots(vector<vector<int>>& points) {
//合并区间
sort(begin(points),end(points),[](vector<int>&pos1,vector<int>& pos2){
return pos1[0]<pos2[0];
});
vector<vector<int> > merged;
merge(points,merged);
return merged.size();
}
//
void merge(vector<vector<int> >& intervals,vector<vector<int> >&res)
{
for(auto& interval:intervals){
int i=interval[0];//左边界
int j=interval[1];//右边界
// [1,2],[3,4] -> [1,2],[3,4]
if(res.empty()||res.back()[1]<i) res.push_back({i,j});
else{
//[1,5],[2,4] -> [2,4] [1,5],[2,6] -> [2,5]
res.back()[0]=max(res.back()[0],i);//左边取小的
res.back()[1]=min(res.back()[1],j);
}
}
}
};