LeetCode452. Minimum Number of Arrows to Burst Balloons题解

来源:互联网 发布:ubuntu 文字编辑 编辑:程序博客网 时间:2024/05/29 18:25

1. 题目描述

这里写图片描述
【翻译过来】:
有若干个气球,给出了它们的直径两个端点的坐标(X轴),我们的工作是需要用一支箭来戳破气球。例如两个气球的直径分别是(1,6)和(2,8),那么我们就可以在x=6的坐标处发射一支箭从而将它们一起戳破。求解的问题是:给出一系列气球直径的坐标之后,最少能用多少支箭就可以戳破它们。
这里写图片描述

2. 样例

Input:[[10,16], [2,8], [1,6], [7,12]]Output:2Explanation:One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).

3. 分析

题目的意思很明确,就是利用最少的箭来戳破气球。分析一下,我们不难得到这样的结论:我们对所有的气球所在的位置进行整理,如果发现两个气球有重叠的部分,就说明它们有可能被同一支箭戳破。
有了这样的一个概念,接下来就是具体做法:我们将所有的气球按照它们的直径左端点进行升序排列,这样我们得到的序列就有了很好的性质:后一个气球很有可能与前一个气球重合。
接下来,我们可以用这样的方法:我们维护一个reference参考区间,这个区间代表的是目前为止最小的气球重合部分,即如果发射箭的话,射箭的坐标就应该在这个reference区间里面,如果接下来的气球左端点都不在这个区间里面,那么它就不会和之前的若干个气球一起被射中了,就要用新的箭。
即:这个贪心算法的思想就是:目前reference参考区间维护的是到目前为止能够被一起射中的气球的重叠部分。
进行遍历的时候:判断当前气球的左右坐标与reference区间关系:

  • 如果该气球在区间内部,说明该气球可以和之前的气球一起被射中,区间需要缩小至该气球的左右端点;
  • 如果左端点在区间内部,右端点不在,说明该气球有一部分和区间重合,所以区间需要缩小:右端点不变,左端点为该气球的左端点;
  • 如果左端点不在区间内部,说明该气球与之前的气球不能一起被射中,需要新增一支箭,之前的气球都被戳破,reference变为该气球区间重新探寻;
    这里写图片描述

4. 源码

class Solution {public:    static bool Compare(pair<int, int>point1, pair<int, int>point2) {        if (point1.first <= point2.first) {            if (point1.first == point2.first) {                return point1.second < point2.second;            }            return true;        }        return false;    }    int findMinArrowShots(vector<pair<int, int>>& points) {        int counter = 1;        sort(points.begin(), points.end(), Compare);        pair<int, int>reference;        if (points.size() != 0) {            reference = points[0];        }        for (int i = 0; i < (int)points.size(); i++) {            if (points[i].first <= reference.second) {                if (points[i].second <= reference.second) {                    reference.first = points[i].first;                    reference.second = points[i].second;                }                else {                    reference.first = points[i].first;                }            }            else {                counter++;                reference = points[i];            }        }        if (points.size() == 0) {            return 0;        }        return counter;    }};

5. 心得

这道题,我自己设计的解法居然能够打败98.95%的人,有点小开心。尽管刚开始走了一点弯路:认为只要每一个气球与前一个气球有重叠部分就可以一起射中,这个错误的思路导致了我提交了3次的Wrong Answer,因为只与前一个气球重叠,不代表和再之前的能够重叠。

0 0
原创粉丝点击