当前位置: 面试刷题>> 用最少数量的箭引爆气球(经典算法150题)


### 题目描述 在一条直线上,有`n`个气球排列着,每个气球都有一个水平位置`x`和一个半径`r`,表示气球的中心位于`x`且其覆盖的区间是`[x-r, x+r]`。现在,你有一支箭,可以水平地射向任意位置,箭一旦射出就会贯穿所有在其路径上的气球(即气球的中心位于箭的路径上或气球被箭的半径所覆盖)。请问,你至少需要射出多少支箭才能引爆所有气球? ### 示例 假设有`n = 6`个气球,其位置和半径如下: ``` [[10,5],[16,2],[2,8],[1,6],[7,2],[12,1]] ``` - 第一个气球:[10,5],覆盖区间是[5, 15] - 第二个气球:[16,2],覆盖区间是[14, 18] - 第三个气球:[2,8],覆盖区间是[-6, 10] - 第四个气球:[1,6],覆盖区间是[-5, 7] - 第五个气球:[7,2],覆盖区间是[5, 9] - 第六个气球:[12,1],覆盖区间是[11, 13] 在这个例子中,我们至少需要射两支箭来引爆所有气球。第一支箭射在`x=6`的位置(或任何[5,7]之间的位置),引爆第三、第四个和第五个气球;第二支箭射在`x=14`的位置(或任何[14,15]之间的位置),引爆第一个和第二个气球。第六个气球由于不与任何已引爆的气球重叠,需要单独一支箭来引爆,但由于它已经被第一支箭的路径所覆盖,因此实际上不需要额外的箭。 ### 解题思路 这个问题可以通过贪心算法来解决。首先,我们需要根据气球的结束位置(即`x+r`)进行排序,因为如果两个气球的结束位置相近,那么它们的引爆位置可能相同,这样可以同时引爆多个气球。然后,我们遍历排序后的气球数组,尽量将箭射在能引爆最多气球的位置(即当前气球的开始位置,因为它是在当前考虑的气球中结束位置最早的)。 ### PHP 代码示例 ```php function findMinArrowShots($points) { if (empty($points)) return 0; // 根据气球的结束位置排序 usort($points, function($a, $b) { return $a[0] + $a[1] <=> $b[0] + $b[1]; }); $count = 1; // 至少需要一支箭 $end = $points[0][0] + $points[0][1]; // 当前箭的结束位置 for ($i = 1; $i < count($points); $i++) { if ($points[$i][0] > $end) { // 如果当前气球的开始位置大于当前箭的结束位置,则需要新箭 $count++; $end = $points[$i][0] + $points[$i][1]; } } return $count; } // 示例 $balloons = [[10,5],[16,2],[2,8],[1,6],[7,2],[12,1]]; echo findMinArrowShots($balloons); // 输出 2 ``` ### Python 代码示例 ```python def findMinArrowShots(points): if not points: return 0 # 根据气球的结束位置排序 points.sort(key=lambda x: x[0] + x[1]) count = 1 end = points[0][0] + points[0][1] for i in range(1, len(points)): if points[i][0] > end: count += 1 end = points[i][0] + points[i][1] return count # 示例 balloons = [[10,5],[16,2],[2,8],[1,6],[7,2],[12,1]] print(findMinArrowShots(balloons)) # 输出 2 ``` ### JavaScript 代码示例 ```javascript function findMinArrowShots(points) { if (points.length === 0) return 0; // 根据气球的结束位置排序 points.sort((a, b) => a[0] + a[1] - (b[0] + b[1])); let count = 1; let end = points[0][0] + points[0][1]; for (let i = 1; i < points.length; i++) { if (points[i][0] > end) { count++; end = points[i][0] + points[i][1]; } } return count; } // 示例 const balloons = [[10,5],[16,2],[2,8],[1,6],[7,2],[12,1]]; console.log(findMinArrowShots(balloons)); // 输出 2 ``` 以上代码均实现了用最少数量的箭引爆气球的问题,并给出了PHP、Python和JavaScript的示例实现。
推荐面试题