题目描述:
有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。
一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。
给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。
解题思路:思路不唯一,我就是把这道题变相成合并区间,并且是求区间的交集,因为射箭是在交集才能一箭N中,具体步骤见注释~
代码实现
class Solution {
/**
* 1. 先将二维数组按照左区间从小到大进行排序
* 2. 合并区间,当发现左区间有重合的时候,需要将右边界更新为小的那个,因为要和下一个区间比较,保证三个都有相交的才行
* 3. 返回二维区间的秩即可
*/
public int findMinArrowShots(int[][] points) {
// 本质是区间合并,不一样的是当发现左区间有重合的时候,需要将右边界更新为小的那个,因为要和下一个区间比较,保证三个都有相交的才行
Arrays.sort(points,(x,y) -> Integer.compare(x[0], y[0]));
// 新建一个二维数组,存放合并后的新的区间
List<int[]> res = new LinkedList<int[]>();
int m = points.length;
int start = 0;
int end = 0;
int k = 1;
res.add(points[0]);
while (k < m) {
// 先判断右边界是否 > 下一个的左边界
if (points[k][0] > res.get(res.size()-1)[1]){//无相交,则直接加进去
res.add(points[k]);
}else {// 有相交,找两个区间的交集,也就是箭可以射的区间
start = Math.max(points[k][0], res.get(res.size()-1)[0]);// 左区间找最大
end = Math.min(points[k][1], res.get(res.size()-1)[1]);// 右区间找最小
res.remove(res.size()-1);// 需要先移除最后一个,再添加,不然就重复了
res.add(new int[]{start,end});
}
k++;
}
// for (int i = 0; i < res.size(); i++) {
// System.out.println(Arrays.toString(res.get(i)));
// }
return res.size();
}
}