1. 程式人生 > >Leetcode 452 .Minimum Number of Arrows to Burst Balloons

Leetcode 452 .Minimum Number of Arrows to Burst Balloons

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:

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

Output:
2

Explanation:
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).
題意就是給出一些氣球,想辦法用最少的次數刺破這些氣球。他們的位置用x軸上的一個區間表示,如果某些氣球的區間存在交集,則可以同時刺破這些氣球。

可以利用貪心演算法的思想。一開始我想出了一種方法,最後有很多樣例過不了,仔細想想是不完備的演算法。就是每次選一個氣球,然後對後面的氣球不斷取交集,來抵消其他的氣球。仔細想可以發現這樣並不一定保證得到最優解。

class Solution {
public:
    int findMinArrowShots(vector<pair<int, int>>& points) {
        int left, right;
        int count = 0;
        for (int i = 0; i < points.size(); i++) {
            if (points[i].first != 0 && points[i].second != 0) {
                count++;
                left = points[i].first;
                right = points[i].second;
            }
            else {
                continue;
            }
            for (int j = 1; j < points.size(); j++) {


                if (points[j].first >= left&&points[j].second <= right) {
                    left = points[j].first;
                    right = points[j].second;
                    points[j].first = 0;
                    points[j].second = 0;
                }
                else if (points[j].first <= left&&points[j].second >= right) {
                    // no change
                    points[j].first = 0;
                    points[j].second = 0;
                }
                else if (points[j].first <= left&&points[j].second <= right&&points[j].second>=left) {
                    right = points[j].second;
                    points[j].first = 0;
                    points[j].second = 0;
                }
                else if (points[j].first >= left&&points[j].first<=right&&points[j].second >= right) {
                    left = points[j].first;
                    points[j].first = 0;
                    points[j].second = 0;
                }
            }
        }
        return count;
    }
};

標準的答案很好理解,就是按照這些氣球的區間的結束位置從小到大先來一次排序,然後每次都刺向這些區間的結束位置。保證消滅最多的氣球。時間複雜度o(nlogn)

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