Minimum Number of Arrows to Burst Balloons

Leetcode-Algorithm-Greedy-452

题目:
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.
(有一些球形的气球分布在一个二维的平面上,每个气球我们给定它在 x 轴上的坐标,因为箭是从x轴的点上沿 y 轴方向垂直射出的,因此气球的y坐标可以忽略。若箭是从点 x 射出,气球的横向坐标为Xstart Xend ,当 Xstart<=x<=Xend 时就可以将气球打爆。由于气球的横坐标有可能重叠,因此最少可以用多少支箭将所有的气球打爆。)

例子:
输入:[[10,16], [2,8], [1,6], [7,12]]
输出:2
(也就是说,最少用2支箭就可以将这些坐标表示的气球全部打爆。)


题解:
方法:(贪心算法)
如果用最少数量的箭将所有的气球打爆,那么每射出一支箭,就要打爆尽可能多的气球。因为只有当气球有重叠的时候才能同时打爆,因此问题成为找到尽可能多的气球,它们在 x 轴的某一点上重叠,这样用一支箭就能把气球都打爆,剩下的气球用同样的方式继续,直到所有气球的打爆了。

class Solution {
public:
    int findMinArrowShots(vector<pair<int, int>>& points) {
        if (points.empty()) return 0;

        //记录所有的气球的位置,若起始位置相同,看成是同一个气球
        multimap<int, int> balloons;
        for (auto point : points)        
            balloons.insert(point);

        int ballNum = balloons.size();
        int arrowNum = 0;

        vector<int> burst;
        while (ballNum > 0) {
            map<int, int>::iterator iter = balloons.begin();
            int start = iter->first;
            int end = iter->second;
            burst.push_back(start);

            //找到一支箭可以打爆的尽可能多的气球。
            while (++iter != balloons.end()) {
                if (iter->first > end)
                    break;
                burst.push_back(iter->first);
                start = iter->first;
                end = (iter->second > end ? end : iter->second);
            }

            //气球打爆了,在列表中去掉。
            ballNum -= burst.size();
            for (int i = 0; i < burst.size(); ++i)
                balloons.erase(burst[i]);
            burst.clear();
            ++arrowNum;
        }

        return arrowNum;
    }
};

分析:
由于算法开始的时候,用一个multimap来重新存储气球的坐标,目的是为了将给定的气球坐标排好序,好让箭能从坐标0点开始往后依次把气球打爆。若不考虑multimap自身的排序功能所消耗的时间的话,存储所用的时间复杂度为 O(n) 。打爆气球的代码段虽然用了嵌套的循环语句,但实际上只把整个multimap容器遍历了一遍,所以时间复杂度为 O(n) 。综上可知,整个算法的时间复杂度为 O(n)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值