用最少数量的箭引爆气球
难度:
标签:
题目描述
有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points
,其中points[i] = [xstart, xend]
表示水平直径在 xstart
和 xend
之间的气球。你不知道气球的确切 y 坐标。
一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x
处射出一支箭,若有一个气球的直径的开始和结束坐标为 x
start
,x
end
, 且满足 xstart ≤ x ≤ x
end
,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。
给你一个数组 points
,返回引爆所有气球所必须射出的 最小 弓箭数 。
示例 1:
输入:points = [[10,16],[2,8],[1,6],[7,12]] 输出:2 解释:气球可以用2支箭来爆破: -在x = 6处射出箭,击破气球[2,8]和[1,6]。 -在x = 11处发射箭,击破气球[10,16]和[7,12]。
示例 2:
输入:points = [[1,2],[3,4],[5,6],[7,8]] 输出:4 解释:每个气球需要射出一支箭,总共需要4支箭。
示例 3:
输入: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
代码结果
运行时间: 116 ms, 内存: 48.4 MB
/*
题目思路:
同上,在 Java Stream 中,我们可以使用 stream 来对数组进行排序,并利用 reduce 函数来计算最少的箭数。对于每个气球,我们检查当前气球的开始位置是否大于之前的箭的结束位置,如果是则增加箭的数量,并更新箭的结束位置。
*/
import java.util.Arrays;
public class Solution {
public int findMinArrowShots(int[][] points) {
return Arrays.stream(points)
// 按结束位置排序
.sorted((a, b) -> Integer.compare(a[1], b[1]))
// 使用 reduce 来计算最小箭数
.reduce(new int[]{0, Integer.MIN_VALUE}, (result, point) -> {
// 如果当前气球的开始位置大于箭的结束位置
if (point[0] > result[1]) {
result[0]++; // 增加箭的数量
result[1] = point[1]; // 更新箭的结束位置
}
return result;
}, (a, b) -> a)[0]; // 返回箭的数量
}
}
解释
方法:
这个题解的思路是先按照气球结束坐标从小到大排序,然后从前往后遍历气球,用一支箭尽可能多地引爆气球。具体来说,初始化一个 pos 变量表示上一支箭的引爆位置,初始化为第一个气球的结束坐标。从第二个气球开始遍历,如果当前气球的开始坐标大于 pos,说明之前的箭无法引爆当前气球,需要增加一支箭,并更新 pos 为当前气球的结束坐标。遍历结束后,ans 即为最少需要的弓箭数。
时间复杂度:
O(nlogn)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在解决这个问题时选择按气球的结束坐标进行排序而不是开始坐标?
▷🦆
排序气球的结束坐标有什么特别的好处,能否解释其在算法中的作用?
▷🦆
在算法中,如果存在多个气球具有相同的结束坐标,这种情况如何处理?会影响箭的数量吗?
▷🦆
题解中提到的变量`pos`的更新策略为什么是在需要新箭时才更新?是否有其他策略可以减少箭的数量?
▷相关问题
无重叠区间
给定一个区间的集合 intervals
,其中 intervals[i] = [starti, endi]
。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
示例 1:
输入: intervals = [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:
输入: intervals = [ [1,2], [1,2], [1,2] ] 输出: 2 解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:
输入: intervals = [ [1,2], [2,3] ] 输出: 0 解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
提示:
1 <= intervals.length <= 105
intervals[i].length == 2
-5 * 104 <= starti < endi <= 5 * 104