一起学算法-452. 用最少数量的箭引爆气球

一、题目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<vector<int>>& points) {
        // 对于empty
        if (points.empty()){
            return 0;
        }  
        // 按照区间开始位置排序
        sort(points.begin(), points.end(),
            [](const vector<int> &a, const vector<int> 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<vector<int>>& points) {
        // 对于empty
        if (points.empty()) {
            return 0;
        }
        sort(points.begin(), points.end(), [](const vector<int>& u, const vector<int>& v) {
            return u[1] < v[1];
        });
        int pos = points[0][1];
        int ans = 1;
        for (const vector<int>& 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++方法二中对区间右端排序处理起来要比方法一快许多,似乎这类问题选择区间右端排序要快上许多。

c++两种方法比较

之前说过php二维数组排序支持上不是很好(算法入门-435. 无重叠区间 - 简书),这里使用了usort()函数自定义排序方法优化了二维数组排序问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容