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

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

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstartxend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 x``startx``end, 且满足 xstart ≤ x ≤ x``end,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points返回引爆所有气球所必须射出的 最小 弓箭数

示例 1:

输入:points = [[10,16],[2,8],[1,6],[7,12]]
输出:2
解释:气球可以用2支箭来爆破:
-在x = 6处射出箭,击破气球[2,8]和[1,6]。
-在x = 11处发射箭,击破气球[10,16]和[7,12]。

示例 2:

输入:points = [[1,2],[3,4],[5,6],[7,8]]
输出:4
解释:每个气球需要射出一支箭,总共需要4支箭。

示例 3:

输入:points = [[1,2],[2,3],[3,4],[4,5]]
输出:2
解释:气球可以用2支箭来爆破:
- 在x = 2处发射箭,击破气球[1,2]和[2,3]。
- 在x = 4处射出箭,击破气球[3,4]和[4,5]。

提示:

  • 1 <= points.length <= 10^5
  • points[i].length == 2
  • -2^31 <= xstart < xend <= 2^31 - 1

按结束位置升序排序

类似合并区间。

class Solution {
    public int findMinArrowShots(int[][] points) {
        // 如果没有气球,返回0,因为不需要任何箭
        if (points.length == 0) {
            return 0;
        }

        // 按照每个气球的起始位置进行升序排序
        // 这里不能使用lambda表达式进行排序,因为`i[0] - j[0]`会出现越界问题。解决方案:1.使用匿名内部类,重写compare方法;2.将points转为long类型
        // Arrays.sort(points, (i, j) -> (i[0] - j[0]));
        Arrays.sort(points, new Comparator<int[]>() {
            public int compare(int[] point1, int[] point2) {
                if (point1[0] > point2[0]) {
                    return 1; // 如果point1的起始位置大于point2的起始位置,返回1
                } else if (point1[0] < point2[0]) {
                    return -1; // 如果point1的起始位置小于point2的起始位置,返回-1
                } else {
                    return 0; // 如果两个起始位置相等,返回0
                }
            }
        });

        // 初始化箭的位置为第一个气球的结束位置
        int pos = points[0][1];
        // 至少需要一支箭
        int ans = 1;

        // 遍历所有的气球
        for (int i = 1; i < points.length; i++) {
            // 如果当前气球的起始位置小于等于上一支箭的位置,说明可以用同一支箭射穿。注意是和上一支箭的位置比较,不是与上一个气球的结束位置比较。
            if (points[i][0] <= pos) {
                // 注意,这里要更新箭的位置为当前气球结束位置与当前箭位置的最小值,因为第二个区间有可能完全被第一个区间盖住,所以要取终点的最小值,把箭的活动范围限制在最小的终点前。
                pos = Math.min(pos, points[i][1]);
            } else {
                // 如果当前气球的起始位置大于箭的位置,说明当前箭不能射穿这个气球
                pos = points[i][1]; // 更新箭的位置为当前气球的结束位置
                ++ans; // 需要增加一支箭
            }
        }

        // 返回需要的最少箭数
        return ans;
    }
}
  • 时间复杂度O(nlogn),排序需要O(nlogn),for循环需要O(n)。
  • 空间复杂度O(logn),即排序需要的栈空间。

按起始位置降序排序

class Solution {
    public int findMinArrowShots(int[][] points) {
        // 如果没有气球,返回0
        if (points.length == 0) {
            return 0;
        }

        // 按照每个气球的起始位置进行降序排序
        Arrays.sort(points, new Comparator<int[]>() {
            public int compare(int[] point1, int[] point2) {
                return Long.compare((long)point2[0], (long)point1[0]); // 起始位置降序排序
            }
        });

        // 初始化箭的位置为第一个气球的起始位置
        int pos = points[0][0];
        // 至少需要一支箭
        int ans = 1;

        // 遍历所有的气球
        for (int[] balloon : points) {
            // 如果当前气球的结束位置小于箭的位置,说明当前箭不能射穿这个气球
            if (balloon[1] < pos) {
                // 更新箭的位置为当前气球的起始位置
                pos = balloon[0];
                // 需要增加一支箭
                ++ans;
            } // 因为起始位置是降序的,所以不用写
            // else {
            //    pos = Math.max(pos, balloon[0]);
            //}
        }

        // 返回需要的最少箭数
        return ans;
    }
}
  • 时间复杂度O(nlogn),排序需要O(nlogn),for循环需要O(n)。
  • 空间复杂度O(logn),即排序需要的栈空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值