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

搞定!撒花🎉~~~

相关推荐
2402_857589368 分钟前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
HBryce2412 分钟前
缓存-基础概念
java·缓存
一只爱打拳的程序猿27 分钟前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring
杨荧28 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
minDuck30 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
linsa_pursuer38 分钟前
快乐数算法
算法·leetcode·职场和发展
XuanRanDev44 分钟前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
代码猪猪傻瓜coding1 小时前
力扣1 两数之和
数据结构·算法·leetcode
为将者,自当识天晓地。1 小时前
c++多线程
java·开发语言