leetcode-452. 用最少数量的箭引爆气球

贪心算法

变相区间问题

leetcode-435解法相同,但有细微差别


题目详情

在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。

一支弓箭可以沿着 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

我的代码:

C++

class Solution 
{
public:
    int findMinArrowShots(vector<vector<int>>& points) 
    {
        if(points.empty())
            return 0;
            int arrs=1;
            sort(points.begin(),points.end(),[](vector <int>& x,vector <int>& y)
            {
                return x[1]<y[1];
            }
            );
           int tem=points[0][1];
            for(int i=1;i<points.size();++i)
            {
                if(points[i][0]>tem)
               { 
                        ++arrs;
                     tem=points[i][1];
               }
            }
            return arrs;
    }
};

Java

class Solution {
    public int findMinArrowShots(int[][] points) {

        if (points.length == 0) return 0;

        int arrs = 1; //最少需要射一箭
        //按照气球的xend进行排序
        Arrays.sort(
            points, new Comparator<int[]>(){
                public int compare(int[] a,int[] b){
                    /*
                     * likou新增了用例[[-2147483646,-2147483645],[2147483646,2147483647]]
                     * 如果利用a[1] - b[1]就会产生溢出!
                     * 
                     */
                    return a[1]<b[1]?-1:1;
                }
            }
        );
        //temp从第一个气球的xend进行比较来决定是否再射一箭
        int temp = points[0][1]; 
        for (int[] point: points){
        //若下一个气球的xstart>上一个的xend,即两个气球无法一箭双雕    
            if (point[0] > temp){
                ++arrs;     //再射一箭
                temp = point[1]; //更新temp继续比较
            }
        }

        return arrs;

    }
}

涉及知识点:

  1. 贪心算法

顾名思义,
贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最
后得到的结果是全局最优的。

思路:

同类型题目435
区间按照结尾从小到大排序,循环数组,如果后面一个区间的开始大于前一个区间的结尾 就需要新增一支箭。

本题和435的细微区别:
435在逐个比较区间时,取的是后面的区间头小于前面的区间尾的情况(即区间有重合),然后进行removed++
452在逐个比较气球时,取的是后面的气球xstart大于前面的气球xend的情况(即区间无重合),然后进行arrs++;
此外注意452需要初始化arrs=1,即至少射一箭
也需要注意在自定义比较规则时的return处溢出情况!

posted @ 2022-03-20 17:59  ggaoda  阅读(13)  评论(0编辑  收藏  举报  来源