当前位置: 首页 > news >正文

贪心算法专题(十一):一箭双雕的快乐——「用最少数量的箭引爆气球」

哈喽各位,我是前端小L。

欢迎来到贪心算法专题第十一篇!

想象一下,墙上贴着一排气球,每个气球都有一个水平覆盖范围 [start, end]。

你是神射手,可以垂直射出一支箭。只要箭的 X 坐标在气球的覆盖范围内,气球就会爆炸。

贪心目标: 找准所有气球重叠最密集的地方射箭,争取用最少的箭引爆所有气球。

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

https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/

题目分析:

  • 输入points数组,元素为[xstart, xend]

  • 输出:最少箭数。

例子:[[10,16], [2,8], [1,6], [7,12]]

  • 气球 A:1~6

  • 气球 B:2~8

  • 气球 C:7~12

  • 气球 D:10~16

如果我们乱射,可能需要 4 支箭。

但如果我们精打细算:

  • x=6射一箭:引爆 A(1~6) 和 B(2~8)。

  • x=11射一箭:引爆 C(7~12) 和 D(10~16)。

  • 共需 2 支箭。

核心思维:寻找“重叠区间”

我们要想一箭穿透多个气球,这几个气球必须在垂直方向上有重叠。

问题转化为:如何找到这组气球的公共重叠区域?

第一步:排序

既然是区间,肯定要让它们有序排列才能方便判断。我们通常按起始位置 (Start) 从小到大排序。

  • 排序前:[[10,16], [2,8], [1,6], [7,12]]

  • 排序后:[1,6], [2,8], [7,12], [10,16]

第二步:遍历与更新边界

我们拿第一支箭去瞄准第一个气球 [1, 6]。理论上,这支箭可以射在 1 到 6 之间的任何位置。

为了让这支箭能射中后面更多的气球,我们应该尽可能往右边射(延迟射出),但不能超过 6。

  • 看第二个气球[2, 8]

    • 它的起始位置2小于第一个气球的结束位置6说明有重叠!

    • 这支箭可以同时射中这两个。

    • 关键点:但这支箭的射击范围被压缩了。它必须在[1, 6]里,也必须在[2, 8]里。所以这支箭最远只能射到min(6, 8) = 6

    • 更新当前重叠组的右边界:right = 6

  • 看第三个气球[7, 12]

    • 它的起始位置7大于当前重叠组的右边界6

    • 说明断档了!前面那支箭最远只能射到 6,根本够不着 7。

    • 决策:前面的气球结算,必须射出一支箭了(arrows++)。然后我们拿出一支新箭,瞄准这个新气球[7, 12]

算法流程 (JavaScript)

  1. 特判:如果数组为空,返回 0。

  2. 排序:按start(下标0) 升序排列。

  3. 初始化arrows = 1(只要有气球,至少要一箭)。

  4. 遍历:从第 2 个气球 (i=1) 开始遍历。

    • 如果当前气球.start > 上一个气球.end

      • 无重叠,需要一支新箭。arrows++

    • 如果当前气球.start <= 上一个气球.end

      • 有重叠,省下一支箭。

      • 核心操作:更新当前气球的右边界(模拟求交集)。

      • 当前气球.end = Math.min(当前气球.end, 上一个气球.end)

      • 注:这里我们直接修改数组元素的 end 值,让它作为“当前重叠组的最小右边界”传递给下一次比较。

代码实现

JavaScript

/** * @param {number[][]} points * @return {number} */ var findMinArrowShots = function(points) { if (points.length === 0) return 0; // 1. 按起始位置升序排列 // 注意:a[0] - b[0] 可能会溢出(在C++中),但在JS中 number 是浮点数,一般没事 // 稳妥写法是 (a, b) => a[0] - b[0] points.sort((a, b) => a[0] - b[0]); let arrows = 1; // 至少需要一支箭 // 2. 从第二个气球开始遍历 for (let i = 1; i < points.length; i++) { // 如果当前气球的左边界 > 上一个气球(修正后)的右边界 // 说明完全不沾边,必须新加一支箭 if (points[i][0] > points[i - 1][1]) { arrows++; } else { // 说明有重叠,这支箭可以继续穿透 // 但是,为了能穿透这两个气球,箭必须射在两者较小的那个右边界之内 // 我们更新当前气球的右边界,作为这一组重叠气球的“最远射击位置” points[i][1] = Math.min(points[i][1], points[i - 1][1]); } } return arrows; };

深度辨析:为什么要Math.min

假设气球是A: [1, 10](很大),B: [2, 3](很小且在A内部)。

  • 排序后:A 在前,B 在后。

  • 遍历到 B 时,B.start(2) <= A.end(10),有重叠。

  • 如果我们不更新边界,继续用A.end(10)跟后面的气球比。

  • 假设后面有个气球C: [4, 5]

  • C.start(4) <= A.end(10),看起来好像能一箭穿 A、B、C?

  • 错!你的箭如果要穿过 B,就必须在[2, 3]之间射。如果你在4射箭,虽然能中 A 和 C,但 B 就漏了。

  • 所以,一旦发现重叠,这支箭的有效射击范围就瞬间缩小到了重叠区域(即右边界取最小值3)。这样对比 C 的时候,4 > 3,我们就知道 C 必须用新箭了。

复杂度分析

  • 时间复杂度:$O(N \log N)$。因为有排序。遍历只需要 $O(N)$。

  • 空间复杂度:$O(1)$。除了排序可能需要的栈空间,我们没有使用额外数组。

总结:区间问题的通解

这道题展示了区间问题的标准模板:

  1. 排序(通常按 Start 排序)。

  2. 判断重叠(Start vs PrevEnd)。

  3. 更新边界(取 Min 还是 Max 看具体需求)。


下一题预告:无重叠区间

如果你理解了这一题,那么下一题 LC 435. 无重叠区间 你只需要改两行代码就能通过。

题目问:给定一堆区间,最少移除几个区间,才能让剩下的区间都不重叠?

思考一下:

“最少移除几个”是不是等价于“最多保留几个(不重叠的)”?

而“最多保留几个不重叠的区间”是不是和“最少用几支箭引爆所有气球”有着某种神秘的数学联系?(提示:其实就是一模一样的题!)

下期见!

http://www.jsqmd.com/news/166258/

相关文章:

  • 别再在 BAPI 后直接 COMMIT WORK:把 BAPI_TRANSACTION_COMMIT、COMMIT WORK 与 BAPI buffer 一次讲透
  • 一次拿下 Web Dynpro ABAP 运行时全景:用 IF_WD_APPLICATION 把应用信息、启动环境、客户端能力都摸清
  • Miniconda-Python3.9如何支持PyTorch与TensorRT集成
  • 把后台 Spool 里的错误变成可检索的 Application Log:SAP ABAP 应用日志从配置到封装的实战指南
  • 企业宣传软文公司哪家效果靠谱?2025年终7家服务商权威测评与最终推荐! - 十大品牌推荐
  • Miniconda-Python3.9如何支持PyTorch XLA进行TPU训练模拟
  • PyTorch模型训练慢?先确认Miniconda环境中的CUDA是否正常
  • 保健品软文哪家公司效果好?2025年终7家服务商权威评测及最终推荐! - 十大品牌推荐
  • 大模型微调不再难!伦哥保姆级教程,三步打造专属AI助手,小白也能轻松上手
  • 把 ST22 里的短 Dump 关进笼子:ABAP 程序避免崩溃的体系化手法(含 GUI_UPLOAD、Gateway、RAP 与 Tail Recursion 案例)
  • 网易发稿哪家公司效果更靠谱?2025年终7家服务商权威评测与最终推荐! - 十大品牌推荐
  • 301与302重定向终极指南:SEO场景下的正确选择与实践技巧
  • 数据结构专练(北京集训)
  • 工业数字化平台助力构建全链路设备管理系统
  • 读懂 SAP Shared Memory 与 IMODE:从 ST02 的 Mode List 还原一次用户会话的内存旅程
  • PyTorch模型服务化部署前的Miniconda-Python3.9环境校验
  • K8S中storageClass
  • 大模型开发全攻略:从零训练你的专属AI编程助手,小白也能秒变大神!
  • 避免依赖冲突:用Miniconda-Python3.9构建纯净PyTorch环境
  • Conda index生成索引:Miniconda-Python3.9搭建私有Channel
  • Miniconda-Python3.9环境下多用户共享PyTorch开发环境配置
  • 2026北京昌平区公司纠纷律师事务所推荐指南:权威测评凸显专业优势,胜诉率领先机构盘点,法律问题咨询找靠谱律所不踩坑 - 苏木2025
  • 在Arm架构的ubuntu中,使用qt qmediaplayer播放视频报错Warning: “No decoder available for type ‘video/mpeg...
  • 阿赛姆ESD二极管在笔记本电脑HDMI2.1接口的应用
  • Anaconda prompt启动慢:Miniconda-Python3.9无GUI更快响应
  • Anaconda prompt启动慢:Miniconda-Python3.9无GUI更快响应
  • GitHub热门项目复现利器:Miniconda-Python3.9+PyTorch环境搭建
  • 哪家发稿渠道公司更靠谱?2025年终7家服务商横向评测与专业推荐! - 十大品牌推荐
  • PyTorch安装Mobile Interpreter:Miniconda-Python3.9支持移动端部署
  • Miniconda-Python3.9 + PyTorch:最适合论文复现的技术组合