用最少数量的箭引爆气球

452. 用最少数量的箭引爆气球 - 力扣(LeetCode)

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstartxend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 x``startx``end, 且满足 xstart ≤ x ≤ x``end,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points返回引爆所有气球所必须射出的 最小 弓箭数

示例 1:

1
2
3
4
5
输入:points = [[10,16],[2,8],[1,6],[7,12]]
输出:2
解释:气球可以用2支箭来爆破:
-在x = 6处射出箭,击破气球[2,8][1,6]
-在x = 11处发射箭,击破气球[10,16][7,12]

示例 2:

1
2
3
输入:points = [[1,2],[3,4],[5,6],[7,8]]
输出:4
解释:每个气球需要射出一支箭,总共需要4支箭。

示例 3:

1
2
3
4
5
输入:points = [[1,2],[2,3],[3,4],[4,5]]
输出:2
解释:气球可以用2支箭来爆破:
- 在x = 2处发射箭,击破气球[1,2][2,3]
- 在x = 4处射出箭,击破气球[3,4][4,5]

提示:

  • 1 <= points.length <= 105
  • points[i].length == 2
  • -231 <= xstart < xend <= 231 - 1

首先按第一个元素从小到大排序

重叠的区间的右边界的最小值之前的区间需要一支箭

按照合并区间的思路,把重叠的区间合并,新区间的右边界保留最小值

合并后的区间数就是需要弓箭的数量

image-20231003000142098
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int findMinArrowShots(int[][] points) {
Arrays.sort(points, (a, b) -> Integer.compare(a[0],b[0])); //按照第一个左边从小到大排序
//使用Integer的compare不会溢出

//重叠的区间合并放入list
List<int[]> list = new ArrayList<>();
list.add(new int[] {points[0][0], points[0][1]});
for(int i = 1; i < points.length; i++){
if(points[i][0] <= list.get(list.size()-1)[1]){ //区间重叠,合并,合并后的右端点保留小的
list.get(list.size()-1)[1] = Math.min(list.get(list.size()-1)[1], points[i][1]);
}else{
list.add(new int[] {points[i][0], points[i][1]});
}
}


return list.size();
}
}
  • 时间复杂度:$O(n*log n)$,因为有一个快排
  • 空间复杂度:$O(n)$,有一个快排,最差情况(倒序)时,需要n次递归调用。因此确实需要O(n)的栈空间

区间不合并的解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int findMinArrowShots(int[][] points) {
// 根据气球直径的开始坐标从小到大排序
// 使用Integer内置比较方法,不会溢出
Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));

int count = 1; // points 不为空至少需要一支箭
for (int i = 1; i < points.length; i++) {
if (points[i][0] > points[i - 1][1]) { // 气球i和气球i-1不挨着,注意这里不是>=
count++; // 需要一支箭
} else { // 气球i和气球i-1挨着
points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
}
}
return count;
}
}

用最少数量的箭引爆气球
http://example.com/2023/02/28/算法/贪心/12. 用最少数量的箭引爆气球/
作者
PALE13
发布于
2023年2月28日
许可协议