【陪伴式刷题】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上的这俩参数的)

搞定!撒花🎉~~~

相关推荐
骆晨学长11 分钟前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
是小Y啦12 分钟前
leetcode 106.从中序与后续遍历序列构造二叉树
数据结构·算法·leetcode
AskHarries16 分钟前
利用反射实现动态代理
java·后端·reflect
@月落16 分钟前
alibaba获得店铺的所有商品 API接口
java·大数据·数据库·人工智能·学习
程序猿练习生17 分钟前
C++速通LeetCode中等第9题-合并区间
开发语言·c++·leetcode
liuyang-neu22 分钟前
力扣 42.接雨水
java·算法·leetcode
z千鑫26 分钟前
【人工智能】如何利用AI轻松将java,c++等代码转换为Python语言?程序员必读
java·c++·人工智能·gpt·agent·ai编程·ai工具
Flying_Fish_roe40 分钟前
Spring Boot-Session管理问题
java·spring boot·后端
赚钱给孩子买茅台喝41 分钟前
智能BI项目第四期
java·spring boot·spring cloud·aigc
Ddddddd_1581 小时前
C++ | Leetcode C++题解之第416题分割等和子集
c++·leetcode·题解