【陪伴式刷题】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 points[i] = [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
  • points[i].length == 2
  • -2^31<= x(start)< x(end)<= 2^31- 1

英文版地址

leetcode.com/problems/mi...

中文版描述

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组points,其中points[i] = [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
  • points[i].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(a[0], b[0])),即Integer内置比较方法,不会溢出,案例中有一个int[][] points = {{-2147483646, -2147483645}, {2147483646, 2147483647}};(我就是卡在了这个案例,本地Debug才发现这个例子中-2147483646和2147483646做差会导致超出Integer的范围(Integer的取值范围是从-2147483648 至 2147483647(-2^31至2^31-1))导致排序出错),也可以用我那版中的方法:o1[0] > o2[0] ? 1 : -1;,反正就是避免元素出界。

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

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

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

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

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

改得再直观一点

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

呃,再来。。。

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

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

搞定!撒花🎉~~~

相关推荐
waicsdn_haha2 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
Q_192849990612 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端
Code_流苏15 分钟前
VSCode搭建Java开发环境 2024保姆级安装教程(Java环境搭建+VSCode安装+运行测试+背景图设置)
java·ide·vscode·搭建·java开发环境
XiaoLeisj1 小时前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
禁默1 小时前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood1 小时前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑1 小时前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
gb42152871 小时前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶1 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot