452.気球を破裂させる矢の最小数-間隔の問題
問題の説明
二次元空間には球形の風船がたくさんあります。各バルーンについて、提供される入力は、水平方向のバルーン直径の開始座標と終了座標です。横座標なので縦座標は重要ではなく、始点と終点の横軸がわかれば十分です。開始座標は常に終了座標よりも小さくなります。
弓と矢は、x軸に沿ったさまざまなポイントから完全に垂直に撃つことができます。座標xで矢印を発射します。バルーンの直径の開始座標と終了座標がxstart、xend、およびxstart≤x≤xendの場合、バルーンは爆発します。射撃できる弓矢の数に制限はありません。弓と矢が発射されると、それらは無期限に進むことができます。すべての気球を爆発させるのに必要な最小数の弓と矢を見つけたいと思います。
ポイントの配列を与えます。ここで、ポイント[i] = [xstart、xend]は、すべての気球を爆発させるために発射する必要のある弓と矢の最小数を返します。
例1:
输入:points = [[10,16],[2,8],[1,6],[7,12]]
输出:2
解释:对于该样例,x = 6 可以射爆 [2,8],[1,6] 两个气球,以及 x = 11 射爆另外两个气球
例2:
输入:points = [[1,2],[3,4],[5,6],[7,8]]
输出:4
例3:
输入:points = [[1,2],[2,3],[3,4],[4,5]]
输出:2
例4:
输入:points = [[1,2]]
输出:1
例5:
输入:points = [[2,3],[2,3]]
输出:1
促す:
0 <= points.length <= 104
points[i].length == 2
-231 <= xstart < xend <= 231 - 1
回答
この質問は435に似ています。これは間隔の問題ですが、微妙な違いがあります。
まず、問題を分析しましょう
。問題を解決するには、すべての気球を撃つために必要な矢印の数=できるだけ少ない矢印を使用し、通過する必要があります。すべての間隔を通して。
- 右の終点に従って間隔を並べ替えます
- サブ問題:左端の間隔から始めて、矢印の位置を右の終点に配置すると、最大の利益を保証できます
- 次に、トラバースを続けて、左の終点が前の矢印の右側にある間隔を見つけ、前の手順に従ってそれを解決し続けます。
コード
class Solution {
public int findMinArrowShots(int[][] points) {
// 贪心问题:所需弓箭数量最小===弓箭尽可能穿过更多的气球
// 和区间问题类似 排序
// 当气球达到当前最左边区间的最右端时 为最大范围
// 代码优化
if(points.length == 0 || points == null ){
return 0;
}
// 排序
Arrays.sort(points,new Comparator<int[]>(){
public int compare(int[] point1,int[] point2){
if(point1[1]>point2[1]){
return 1;
}else if(point1[1]<point2[1]){
return -1;
}else{
return 0;
}
}
});
// 获取长度
int length = points.length;
// 准备弓箭计数
int num = 1;
// 设置右边界 right
int right = points[0][1];
for(int i=1;i<length;i++){
if(points[i][0]>right){
num++;
right = points[i][1];
}
}
return num;
}
}