Minimum Number of Arrows to Burst Balloons 用最少数量的箭引爆气球

本文探讨了一种算法问题,即如何在二维空间中利用最少数量的箭矢射爆所有气球。通过将问题转化为无重叠区间问题,采用排序和遍历的方法找到了最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了。开始坐标总是小于结束坐标。平面内最多存在104个气球。

一支弓箭可以沿着x轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足  xstart ≤ x ≤ xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。

Example:

输入:
[[10,16], [2,8], [1,6], [7,12]]

输出:
2

解释:
对于该样例,我们可以在x = 6(射爆[2,8],[1,6]两个气球)和 x = 11(射爆另外两个气球)。

思路:这道题可以转化成Non-overlapping Intervals 无重叠区间来做,求出无重叠的区间个数就是箭头一次性能射穿的气球个数,具体思路请点击链接部分。

参考代码:

class Solution {
public:
static bool pointsCmp(const pair<int, int> &a, const pair<int, int> &b) {
	return a.second < b.second;
}
int findMinArrowShots(vector<pair<int, int>>& points) {
	if (points.size() == 0) return 0;
	sort(points.begin(), points.end(),pointsCmp);
	pair<int, int> last = points[0];
	int count = 1;
	for (int i = 1; i < points.size(); i++) {
		if (points[i].first <= last.second && last.second <= points[i].second) continue;
		else {
			count++;
			last = points[i];
		}
	}
	return count;
}
};

 

这段代码是用来解决“最少数量引爆气球”这个问题的经典算法实现。下面我会详细介绍它的功能和工作原理: ### 功能概述 给定一系列二维平面上表示气球位置的区间(即每一个气球对应一段水平线段),目标是找到最少数量的垂直能够射爆所有的气球。 ### 代码分析 #### 1. **类及函数声明** ```cpp class Solution { public: int findMinArrowShots(vector<vector<int>>& points); }; ``` - 这里定义了一个名为Solution的类,其中包含公共成员函数findMinArrowShots。 - 此函数接收一个参数`points`,这是一个存储了多个气球区间的二维向量。 #### 2. **排序步骤** ```cpp ranges::sort(points, {}, [](auto& p) { return p[1]; }); // 按照右端点从小到大排序 ``` - 调用了C++20引入的新特性`std::ranges::sort`来对`points`进行排序。 - 排序基于每个气球区间的结束坐标(p[1]),使得数组按照这些坐标的递增次序排列。 #### 3. **初始化计数变量和前驱标记** ```cpp int ans = 0; // 计算所需最小矢数目 long long pre = LLONG_MIN; // 初始设置为不可能达到的小值 ``` - `ans`: 初始化为零,用来记录需要多少支才能击破全部气球。 - `pre`: 首先设定成非常小的一个数字(`LLONG_MIN`),以便后续比较时可以保证第一次循环一定能满足条件更新它。 #### 4. **遍历并计算最少数** ```cpp for (auto& p : points){ if (p[0] > pre){ // 当当前气球开始位置大于上一支的位置,则增加数量 ans++; pre = p[1]; // 更新新的头放置在当前气球结尾处 } } ``` - 循环检查每个气球是否能被之前的一支射中。 - 条件判断:如果当前气球起始位置超过上次射击范围(pre),则需新增一只(即`ans++`)并将此新设于现气体球末端作为下次参照基准。 #### 5. **返回结果** ```cpp return ans; ``` 最后返回总所需的最少数量。 --- ### 示例说明 假设输入如下: ```txt [[10,16],[2,8],[1,6],[7,12]] ``` 经过上述过程处理后得到的结果将是: ```txt 2 ``` 解释:你可以分别从x=6 和 x=11两个地方发射两枚即可覆盖所有气球区域。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值