【陪伴式刷题】Day 30|贪心算法|452.用最少数量的箭引爆气球🎈(Minimum Number of Arrows to Burst Balloons)

放在最前面的!!!当看到注意事项📋里有 -2^31<= x(start)< x(end)<= 2^31- 1 的时候,使用int类型的参数就要注意是否会越界叻!!!

题目描述

英文版描述

There are some spherical balloons taped onto a flat wall that represents the XY-plane. The balloons are represented as a 2D integer array points where pointsi = x(start), x(end) denotes a balloon whose horizontal diameter stretches between x(start) and x(end). You do not know the exact y-coordinates of the balloons.

Arrows can be shot up directly vertically (in the positive y-direction) from different points along the x-axis. A balloon with x(start) and x(end) is burst by an arrow shot at x if x(start) <= x <= x(end). There is no limit to the number of arrows that can be shot. A shot arrow keeps traveling up infinitely, bursting any balloons in its path.

Given the array points, return the minimum number of arrows that must be shot to burst all balloons.

Example 1:

  • Input: points = \[10,16,2,8,1,6,7,12] Output: 2 Explanation: The balloons can be burst by 2 arrows: Shoot an arrow at x = 6, bursting the balloons 2,8 and 1,6. Shoot an arrow at x = 11, bursting the balloons 10,16 and 7,12.

Example 2:

Input: points = \[1,2,3,4,5,6,7,8] Output: 4 Explanation: One arrow needs to be shot for each balloon for a total of 4 arrows.

Example 3:

  • Input: points = \[1,2,2,3,3,4,4,5] Output: 2 Explanation: The balloons can be burst by 2 arrows: Shoot an arrow at x = 2, bursting the balloons 1,2 and 2,3. Shoot an arrow at x = 4, bursting the balloons 3,4 and 4,5.

Constrains:

  • 1 <= points.length <= 10^5
  • pointsi.length == 2
  • -2^31<= x(start)< x(end)<= 2^31- 1

英文版地址

leetcode.com/problems/mi...

中文版描述

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组points,其中pointsi = x(start), x(end)表示水平直径在x(start)和x(end)之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 x(start,)x(end,) 且满足x(start)≤ 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
  • pointsi.length == 2
  • -2^31<= x(start)< x(end)<= 2^31- 1

中文版地址

leetcode.cn/problems/mi...

解题方法

俺这版

有点过于慢了哈= =

java 复制代码
class Solution {
    public int findMinArrowShots(int[][] points) {
        if (points == null) {
            return 0;
        }
        if (points.length == 1) {
            return 1;
        }
        Arrays.sort(points, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[0] != o2[0]) {
                    return o1[0] > o2[0] ? 1 : -1;
                } else {
                    return o1[1] > o2[1] ? 1 : -1;
                }
            }
        });
        long[] step = new long[2];
        step[0] = points[0][0];
        step[1] = points[0][1];
        int result = 1;
        for (int i = 1; i < points.length; i++) {
            if (step[1] >= points[i][0]) {
                if (step[1] > points[i][1]) {
                    step[0] = points[i][0];
                    step[1] = points[i][1];
                }
            } else {
                result++;
                step[0] = points[i][0];
                step[1] = points[i][1];
            }
        }
        return result;
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组大小
  • 空间复杂度:O(1)

官方版

java 复制代码
class Solution {
    public int findMinArrowShots(int[][] points) {
        Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
        int count = 1;
        for (int i = 1; i < points.length; i++) {
            if (points[i][0] > points[i - 1][1]) {
                count++;
            } else {
                points[i][1] = Math.min(points[i][1], points[i - 1][1]);
            }
        }
        return count;
    }
}

复杂度分析

  • 时间复杂度:O(NlogN),其中 n 是数组大小,主要是排序耗费的时间
  • 空间复杂度:O(logN),java所使用的内置函数用的是快速排序需要 logN 的空间

总结 >> 今天的最近很多嘿嘿( ̄∇ ̄)/

可以看到官方版在执行的时间复杂度、空间复杂度都表现的更好,并且在自定义比较器时,采用Integer.compare(a0, b0)),即Integer内置比较方法,不会溢出,案例中有一个int\[\]\[\] points = {{-2147483646, -2147483645}, {2147483646, 2147483647}};(我就是卡在了这个案例,本地Debug才发现这个例子中-2147483646和2147483646做差会导致超出Integer的范围(Integer的取值范围是从-2147483648 至 2147483647(-2^31至2^31-1))导致排序出错),也可以用我那版中的方法:o10 > o20 ? 1 : -1;,反正就是避免元素出界。

后面的逻辑就很类似了,就是比较然后更新重叠的边界。

根据这个 版本,我考虑了下,其实也没有必要排两次序(第一版慢的原因应该就是排序这里),做了下优化

果然,时间快了很多= =,不过有一点我很迷惑,当我仅仅把比较器中的o10 > o20 ? 1 : -1换成Integer.compare(o10, o20),空间复杂度就优秀了很多(Why?)

我专门看了Integer.compare()方法的源码,也是三目运算符啊🤔

于是我用同样的形式,发现居然空间复杂度也是这么优秀(Why?)

改得再直观一点

只是一个大于小于的差别,空间复杂度就不一样了?当我又执行一次后。。。

呃,再来。。。

同志们啊,Leetcode的这个是时间复杂度跟空间复杂度好像也不是那么靠谱哎(˶‾᷄ ⁻̫ ‾᷅˵),可能是数据集不同导致的差别?(>>>是的吧 = =)

好的,就是这个发现(之前我一直都挺信Leetcode上的这俩参数的)

搞定!撒花🎉~~~

相关推荐
zzu123zsw几秒前
从 SPI 契约到独立 ClassLoader 隔离:Spring Boot 插件热插拔架构设计与内存泄露防御
java·spring boot·后端·架构设计
文丑颜不良啊1 分钟前
LeetCode1161~1180题目解析
java·leetcode
古法老登瞎折腾8 小时前
大数据智能运维实战(十一):运维 MCP 的工程化——权限、限流、审计与错误处理
java·大数据·运维·spring ai·mcp
智能运维指南9 小时前
研制过程“两张皮“怎么破:研制一体化支撑平台的定位、能力边界与落地前提
java·前端·人工智能·嘉为蓝鲸
yz_aiks10 小时前
Spring AI 2.1 ChatMemory 已过时用什么替代:迁移到 Session Memory 实战(JDBC 存储与会话压缩)
java·spring boot·大模型·ai agent·spring ai
金銀銅鐵10 小时前
[Java] 用 GUI 展示 EnumMap 增删键值对时的内部变化
java·后端·ai编程
学长毕设10 小时前
基于SpringBoot的上门洗车服务系统设计与实现
java·spring boot·后端
jason成都10 小时前
RTKLIB-Java 多基线联合RTK:FIX率从0%到91.5%的三层根因修复
java·gnss·rtklib·rtklib_java
鱼宵10 小时前
Stream 终端操作一次讲透:collect、count、reduce 怎么选
java·stream·终端操作
一去不复返的通信er10 小时前
贪心算法-合并区间(LeetCode 56)
算法·leetcode·贪心算法