452. Minimum Number of Arrows to Burst Balloons
题目
There are some spherical balloons taped onto a flat wall that represents the XY-plane. The balloons are represented as a 2D integer array
points
wherepoints[i] = [xstart, xend]
denotes a balloon whosehorizontal diameter
stretches betweenxstart
andxend
. You do not know the exact y-coordinates of the balloons.
Arrows can be shot up
directly vertically
(in the positive y-direction) from different points along the x-axis. A balloon withxstart
andxend
isburst
by an arrow shot atx
ifxstart <= x <= xend.
There is no limit to the number of arrows that can be shot. A shot arrow keeps traveling up infinitely, bursting any balloons in its path.
Given the array
points
, return theminimum
number of arrows that must be shot to burst all balloons.
有不同大小的范围
的气球,用最少的飞镖
将所有气球射爆
传入气球大小阵列范围 [[2,8],[1,6],[7,12]]
索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
第 1 个气球范围 [2,8] |
V | V | V | V | V | V | V | V | |||||
第 2 个气球范围 [1,6] |
V | V | V | V | V | V | |||||||
第 3 个气球范围 [7,12] |
V | V | V | V | V | V |
Example
Input: points = [[10,16],[2,8],[1,6],[7,12]]
Output: 2
Explanation: The balloons can be burst by 2 arrows:
- Shoot an arrow at x = 6, bursting the balloons [2,8] and [1,6].
- Shoot an arrow at x = 11, bursting the balloons [10,16] and [7,12].
Input: points = [[1,2],[3,4],[5,6],[7,8]]
Output: 4
Explanation: One arrow needs to be shot for each balloon for a total of 4 arrows.
Input: points = [[1,2],[2,3],[3,4],[4,5]]
Output: 2
Explanation: The balloons can be burst by 2 arrows:
- Shoot an arrow at x = 2, bursting the balloons [1,2] and [2,3].
- Shoot an arrow at x = 4, bursting the balloons [3,4] and [4,5].
答案
将气球大小按照每个大小的 终点
排序,然后从第一个气球 终点
射出第一隻箭
因为是按照 终点排序
,所以其他气球的终点 一定比前面大
所以当其他气球的起点
小于前面气球终点
时,其他气球一定在射程范围,可以一次射爆
若 其他气球的起点
大于 前面气球终点
,表示这个气球已经脱离射程范围了,需要另一把箭了
- 按照气球大小的
终点
排序所有连线,若终点
相同,则将长度越短
的气球大小排在前面 - 拿
第一个气球
来当作参照比较,所以预设一定要射出 1 支箭
- 若目前
「要检查的气球范围:起点」
小于或等于「前一个气球范围区间:终点」
,表示这个气球可以用上一个气球的飞镖射到,不需要额外的飞镖
- 若目前
「要检查的气球范围:起点」
大于「前一个气球范围区间:终点」
,表示前一个气球的飞镖,射不到这个新的气球区间范围,需要新的飞镖- 拿最新射不到的气球来当作下一隻箭的参考点,将
「新的气球区间范围的终点」
,当作下一个飞镖的位置
,继续检查下一个
- 拿最新射不到的气球来当作下一隻箭的参考点,将
JavaScript
/**
* @param {number[][]} balloonsPointsList
* @return {number}
*/
var findMinArrowShots = function(balloonsPointsList) {
if (balloonsPointsList.length == 0) {
// 如果没有任何资料,直接回传 0
return 0;
}
// 排序清单大小(终点越小排前面)
balloonsPointsList.sort((a, b) => {
if (a[1] < b[1]) {
// 当 a[1] 数字比 b[1] 小,a 较小排前面
return -1;
} else if (a[1] > b[1]) {
// 当 a[1] 数字比 b[1] 大,a 较大排后面
return 1;
} else {
// a[1] 数字 与 b[1] 一样大,表示终点一样,将长度较短的放在前面
if (a[0] < b[0]) {
// 当 a[0] 第一个数字比 b[0] 小,a 较长,a 排后面
return 1;
} else {
// 当 a[1] 第一个数字比 b[1] 大,a 较短,a 排前面
return -1;
}
}
});
// 射飞镖次数,预设为至少 1 个
let arrowShot = 1;
// 从第一个气球范围区间终点射飞镖,所以从这个点开始检查
let previousEndPointer = balloonsPointsList[0][1];
for (let i = 1; i < balloonsPointsList.length; i++) {
// 从第 2 个气球区间开始检查,直到检查完所有气球区间
// 取得目前要检查的气球范围
let currentBalloonsPoint = balloonsPointsList[i];
// 目前气球范围:起点
let currentBalloonsStartPointer = currentBalloonsPoint[0];
// 目前气球范围:终点
let currentBalloonsEndPointer = currentBalloonsPoint[1];
if (currentBalloonsStartPointer <= previousEndPointer) {
// 若目前「要检查的气球范围:起点」小于或等于「前一个气球范围区间:终点」
// 表示这个气球可以用上一个气球的飞镖射到,不需要额外的飞镖
continue;
} else {
// 若目前「要检查的气球范围:起点」大于「前一个气球范围区间:终点」
// 表示前一个气球的飞镖,射不到这个新的气球区间范围,需要新的飞镖
arrowShot++;
// 将「新的气球区间范围的终点」,当作下一个飞镖的位置,继续检查下一个
previousEndPointer = currentBalloonsEndPointer;
}
}
return arrowShot;
};