leetcode 452. Minimum Number of Arrows to Burst Balloons (除掉气球的最小箭数)

There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it’s horizontal, y-coordinates don’t matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons.

An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.

Example:

Input:
[[10,16], [2,8], [1,6], [7,12]]

Output:
2

Explanation:
One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).

题中数组代表气球摆放的直径范围,只考虑x坐标,不考虑y坐标
如[10, 16]代表气球的范围从10到16,一个范围内只需要一支arrow就能把该范围所有气球都burst掉
重叠区域也是只需要一支arrow,比如[1,6]和[2,8]在2~6的任一点放arrow,这两个区间可以同时burst掉

让找出最少的arrow可以把所有区间的气球都burst掉

思路:
这种区间重叠问题,首先想到的是按起始点排序或者终点排序

(1) 按起始点排序的话,需要注意右边界的问题
比如

[1, 100]
[3, 8]
[9, 11]

显然前两个区间一个arrow就能搞定,因为第二个区间起始点3<100
但是如果不更新右边界,还是100
那么第3个区间也能判断用一个arrow搞定,但是[3,8]和[9,11]是不重叠的,必须用2个arrow

所以在有重叠区域时,要把右边界设为较短的那一方
此思路和435题类似

注意在排序比较时可以用Integer.compare, 也可以用a[0] < b[0] ? -1 : 1,
就是不能用a[0] - b[0], 因为start和end的取值范围可以是2-31,相减整数会溢出。

//19ms
    public int findMinArrowShots(int[][] points) {
        Arrays.sort(points,(a,b)->Integer.compare(a[0],b[0]));
        int res = 1;
        int end = points[0][1];

        for(int[] cur : points) {
            if(cur[0] <= end) {     
                end = Math.min(end, cur[1]);
            } else {
                res ++;
                end = cur[1];
            }
        }
        return res;

    }

(2) 按endpoint排序
因为start 一定 < end(题目要求),所以看两个区间(x1, x2) 和 (y1, y2)是否重叠,
取决于y1 是否 < x2。
x1是派不上用场的,因为不管y1在x1的左边还是右边,只要y1 <= x2,就一定重叠,y1 > x2就一定不重叠。
只有不重叠,arrow的个数才会+1.

重叠的话,endpoint要以短的那个为准,但是既然已经按endpoint排序,前面的end一定比后面的end小,所以不需要处理。

java:

//19ms
    public int findMinArrowShots(int[][] points) {
        Arrays.sort(points,(a,b)->Integer.compare(a[1],b[1]));
        int res = 1;
        int end = points[0][1];

        for(int[] cur : points) {
            if(cur[0] > end) {
                res ++;
                end = cur[1];
            }
        }
        return res;
    }

c++

    int findMinArrowShots(vector<vector<int>>& points) {
        if (points.empty()) {
            return 0;
        }
        
        sort(points.begin(), points.end(), [&](vector<int>& a1, vector<int>& a2) {
           return a1[1] < a2[1]; 
        });
        
        int res = 1;
        int right = points.front()[1];
        
        for (const auto& point : points) {
            if (point[0] > right) {
                res ++;
                right = point[1];
            }
        }
        
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值