leetcode 452

由于poj的题我实在刷不动了,所以就过来写leetcode了,这道题是两天前的每日一题,但是我那天没有时间做,就拖到了这个时候。
原题链接:https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/
这道题题目可能有些人读不太明白,我的理解是有几个气球,每个气球都拥有左右两个坐标,因为气球是有宽度的,左边的表示他的起始点,右边是结束点,就例如[10,16],这个气球,无论你在10这个点射一箭或者11射一箭都能射爆这个气球,换句话说,只要你射箭的点在[10,16]这个区间内就可以了。但是此时气球不止一个,你需要求出射出最少多少支箭能达到让所有气球全部射爆的情况。
乍一看我的第一想法就是区间的合并问题,求他们的交集,将所有的区间逐一进行合并。例如[10,16]和[14,20],求他们的交集为[14,16],也就是说,只要在这个区间射出任意一支箭就能达到两个气球一起爆炸的效果。不过为什么是交集呢,可以设想一下无论是在13或者19射一支箭,只能满足让一个气球爆炸,但是题目既然让我们用最少的箭,这当然是行不通的。我们将所有区间合并,看剩下来还剩几个区间,就是应该射出多少箭。
不过我认为这种方案代码量应该不会少,并且时间复杂度也不会低。于是我又想到了一个方案。第一个想法:将所有的气球按照起始点进行从小到大排序,这时候我按照气球的右边界射出一箭,如果他比下一个气球的左边界要大的话,就说明这支箭可以把下一个气球也一起射爆。例如[3,5]和[4,6],我在5这个位置射出一支箭,就可以同时让两个气球都爆,不过我在写完代码的时候发现了一个问题,举个例子:[0,9]和[0,6],此时在代码中9>0他是判定为第二个气球可以爆的,实际上在9发射一支箭,并不在[0,6]这个区间里。所以我又让当左边界相等时,右边界也从小到大排序。不过我发现这并不单单只是在左边界相同时才会发生的事情,例如:[0,9]和[2,8],9发射一支箭,并不在[2,8]这个区间。
或许呢,我刚开始想的就是错的,我考虑按照右边界从小到大进行排序。果然被AC了;
这是我的代码哦。

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.size()==0)
            return 0;
        sort(points.begin(),points.end(),cmp);
        int jian=1,cur=points[0][1];
        for(int i=1;i<points.size();i++)
            if(points[i][0]>cur){
                cur=points[i][1];
                jian++;
            }
        return jian;
    }
    static bool cmp(vector<int>& a,vector<int>& b){
        return a[1]<b[1];
    }
};

非常简短的代码,并且时间复杂度仅为O(n)。不过为什么这样是对的呢?
我不太懂儿数学的证明过程,就用我自己的理解理论上来说明一下它的正确性。
这一组气球由于按照右边界进行从大到小的排序,所以后面的气球的右边界始终大于等于当前气球的右边界。那么按着当前这个气球的右边界发射一支箭的话,只会有两种情况: 1.下一个气球的左边界小于等于这个气球的右边界,下一个气球爆炸 2.下一个气球的左边界大于这个气球的右边界,下一个气球不爆炸。那么这样子的话就可以完全忽略我之前说的那种情况:下一个气球的左边界小于等于这个气球的右边界,但是下一个气球根本不会爆炸。因为后面的气球的右边界始终大于等于这个气球的右边界!!
那么我又考虑到了前面的那个特殊情况,如果当前气球和下一个气球的右边界相等但左边界不等怎么办?是不是需要特殊化处理?经过我的思考,我发现这个方法也可以直接忽略这种情况。设想[2,4]和[3,4],在4发射一箭,无论怎样两个气球都会爆炸。并且无论这两个气球左边界从小到大也好,从大到小也罢,抑或是完全无序,都可以忽略。[2,4] ,[1,4],[3,4]都可以一箭射爆。换个思想,其实按照我们之前那个求交集的思想也可以想像。这三个区间求交集就是[3,4],直接整合成了一个区间,因为他们右边界相等,左边界必定小于右边界,所以无论这样的元素有多少个,整合成的交集都永远只有一个。
可以看出来,其实这道题是使用到了贪心算法,为什么是贪心算法?因为我只在气球的右边界射箭,来达到能让最多的气球爆炸的情况。这里借用我老师的一句话“而对于贪心算法来说,最大的特点就是:通常代码都会比较简单,但要想证明贪心的正确性,会比较费劲。”
最后呢,如果我有什么地方想错了的话,欢迎你们能在评论区指出来,毕竟学习是互相促进的过程。继续加油:)

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值