【小白爬Leetcod452】3.5 用最少数量的箭引爆气球 Minimum Number of Arrows to Burst Balloons

【小白爬Leetcod452】3.5 用最少数量的箭引爆气球 Minimum Number of Arrows to Burst Balloons


Leetcode 452 m e d i u m \color{#FF6347}{medium} medium

点击进入原题链接:Leetcode 452 用最少数量的箭引爆气球 Minimum Number of Arrows to Burst Balloons

题目

discription

There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it’s horizontal, y-coordinates don’t matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons.

An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend . There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.

Example:
在这里插入图片描述

中文描述

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

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

示例:
在这里插入图片描述

尝试一 解答错误…

其实就是求最少交集的过程。

我的思路是:

  1. 新建一个数组intersections存放区气球的最小交集:
  2. 遍历气球数组,对于每一个气球,如果当前的气球和intersections有交集,那么就求他们的交集;若没有,在intersectionspush_back当前气球。
  3. 在求交集方面,首先判断两个气球是否有交集:
if (intersections[j][1] < points[i][0]||intersections[j][0]>points[i][1])

如果if条件成立,说明两个气球没有交集,不成立说明有交集。

  1. 在求交集时,为了避免麻烦,直接讲四个数升序排序,取中间两个数作为新交集。封装成一个新的函数find_intersection
	vector<int> find_intersection(const vector<int>&v1, const vector<int>&v2) {
		vector<int> nums = { v1[0],v1[1],v2[0],v2[1] };
		sort(nums.begin(),nums.end(), less<int>());
		return *new vector<int>{ nums[1],nums[2] };
	}

代码如下:

class Solution {
public:
	int findMinArrowShots(vector<vector<int>>& points) {
		if(points.empty()) return 0;
		vector<vector<int>> intersections;
		intersections.push_back(points[0]);
		for (int i = 1; i < points.size(); i++) {
			bool isnew = true; //判断是否要在intersections里新建一个元素(有交集就不用)
			for (int j = 0; j < intersections.size(); j++) { //遍历每一个intersections看看是否有有交集的
				if (intersections[j][1] < points[i][0]||intersections[j][0]>points[i][1]) {
					continue; //没有交集看看intersections的下一个有没有
				}
				else {
					intersections[j] = find_intersection(intersections[j], points[i]);
					isnew = false;
					break;
				}
			}
			if (isnew) intersections.push_back(points[i]);  //遍历完所有intersections都没有找到交集,那么需要创建新的intersection
		}
		
		return intersections.size();
	}

	vector<int> find_intersection(const vector<int>&v1, const vector<int>&v2) { //找交集的数组
		vector<int> nums = { v1[0],v1[1],v2[0],v2[1] };
		sort(nums.begin(),nums.end(), less<int>());
		return *new vector<int>{ nums[1],nums[2] };
	}
};

结果,死活通不过这个案例
在这里插入图片描述
直到我画图出来才发现去了问题:

在这里插入图片描述
这个例子中,射出6和9两支箭,就可以射爆两只气球,而按照我的算法,最后会出现3个交集:[7,8],[9,10],[0,6],而不是[6,6],[9,9],为什么会出现这种情况呢?

原来,遍历完[0,9],[1,8],[7,8]之后,intersections里的第一个交集就被缩小成了[7,8],当然不包含[0,6]

要解决这个问题,必须要按照一定的顺序去遍历数组。

尝试二 先排序气球…

先排序气球有一下几个好处:

  1. 不用担心尝试一中的问题;
  2. 判断是否有交集变得简单:只要判断intersections里最后一个交集的右界是否大于等于当前待判断气球的左界:

在这里插入图片描述
在这里插入图片描述
3. 求交集也变得简单:
新交集的左边肯定是points[i]的左界,新交集的右边:取pointsp[i]intersections.back()的小值。(这里又踩了一个坑)

完整代码:

class Solution {
public:
    static bool cmp(const vector<int>&v1, const vector<int>&v2){
        return v1[0]<v2[0];
    }
	int findMinArrowShots(vector<vector<int>>& points) {
        if(points.empty()) return 0;
        sort(points.begin(),points.end(),cmp);
		vector<vector<int>> intersections;
		intersections.push_back(points[0]);
    for (int i = 1; i < points.size(); i++) {
        if(intersections.back()[1]>=points[i][0]){
            intersections.back()[1] = intersections.back()[1] > points[i][1] ? points[i][1] : intersections.back()[1];
        }
        else{
            intersections.push_back(points[i]);
        }
	}	
	return intersections.size();
}
};

在这里插入图片描述

尝试三 用vector作甚…

如题,题目只要我返回箭矢的数量,我空费机时,用vector来记录区间没有任何意义,当要用到新区间的时候,老区间就没有存在的意义了。因此用int start_posend_pos来记录区间。

class Solution {
public:
    static bool cmp(const vector<int>&v1, const vector<int>&v2){
        return v1[0]<v2[0];
    }
	int findMinArrowShots(vector<vector<int>>& points) {
        if(points.empty()) return 0;
        sort(points.begin(),points.end(),cmp);
        //用第一个气球来初始化交集的区间
        int cnt = 1;
        int start_pos = points[0][0];
        int end_pos = points[0][1];
    for (int i = 1; i < points.size(); i++) {
        if(end_pos>=points[i][0]){
            end_pos = end_pos > points[i][1] ? points[i][1] : end_pos;
        }
        else{
            start_pos = points[i][0];
            end_pos = points[i][1];
            cnt++;
        }
	}	
	return cnt;
}
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值