一、题目452. 用最少数量的箭引爆气球
LeetCode地址:https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/
难度:中等
在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。
一支弓箭可以沿着 x 轴从不同点完全垂直地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend,且满足 xstart <= x <= xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。
给你一个数组 points ,其中 points [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
提示:
0 <= points.length <= 104
points[i].length == 2
-231 <= xstart < xend <= 231 - 1
二、解题思路
与其他区间类问题的解题思路一样都是贪心思想, 先排序, 然后遍历检查是否满足合并区间的条件
ps:算法入门-435. 无重叠区间 - (jianshu.com)
三、实现过程
c++方法一
class Solution {
public:
int findMinArrowShots(vector>& points) {
// 对于empty
if (points.empty()){
return 0;
}
// 按照区间开始位置排序
sort(points.begin(), points.end(),
[](const vector &a, const vector b) {
return a[0] < b[0];
});
int count = 1;
int len = points.size();
// 右边区间初始化;
int right = points[0][1];
for (int i = 1; i < len; i++) {
//如果下一个区间左端超过当前右区间,换下一个箭
if(points[i][0] > right){
count++;
right = points[i][1];
}else{
if(points[i][1] < right){
right = points[i][1];
}
}
}
return count;
}
};
c++方法二(官方题解)
链接:https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/solution/yong-zui-shao-shu-liang-de-jian-yin-bao-qi-qiu-1-2/
class Solution {
public:
int findMinArrowShots(vector>& points) {
// 对于empty
if (points.empty()) {
return 0;
}
sort(points.begin(), points.end(), [](const vector& u, const vector& v) {
return u[1] < v[1];
});
int pos = points[0][1];
int ans = 1;
for (const vector& balloon: points) {
if (balloon[0] > pos) {
pos = balloon[1];
++ans;
}
}
return ans;
}
};
PHP
class Solution {
/**
* @param Integer[][] $points
* @return Integer
*/
function findMinArrowShots($points) {
if( count($points) == 0 ){
return 0;
}
usort($points,function($value1,$value2){
if( $value1[0] > $value2[0] ){
return 1;
}else if( $value1[0] < $value2[0] ){
return -1;
}else{
if( $value1[1] > $value2[1] ){
return 1;
}else if($value1[1] < $value2[1]){
return -1;
}else{
return 0;
}
}
});
$right = $points[0][1];
$count = 1;
$len = count($points);
for($i = 1;$i < $len;$i++){
if($points[$i][0] > $right){
$count++;
$right = $points[$i][1];
}else{
if($points[$i][1] < $right){
$right = $points[$i][1];
}
}
}
return $count;
}
}
JavaScript
/**
* @param {number[][]} points
* @return {number}
*/
var findMinArrowShots = function(points) {
if(points.length == 0){
return 0;
}
points.sort((a, b) => a[0] - b[0])
//console.log(points)
// 射击次数
var count = 1;
// 维护射击区间的右边界
var right = points[0][1];
for (var i = 1; i < points.length; i++) {
if (points[i][0] > right) { // 新的气球左端点大于射击区间右边界,更新射击区间右边界
count++;
right = points[i][1];
} else { // 新的气球左端点小于等于射击区间的右边界
if (points[i][1] < right) { // 如果右端点也比射击区间右边界小
right = points[i][1];
}
}
}
return count;
};
四、小结
这类区间问题处理思路基本上就是排序 + 贪心,选择哪种排序思路,对后续操作影响是非常大的。在c++方法二中对区间右端排序处理起来要比方法一快许多,似乎这类问题选择区间右端排序要快上许多。
之前说过php二维数组排序支持上不是很好(算法入门-435. 无重叠区间 - ),这里使用了usort()函数自定义排序方法优化了二维数组排序问题。