LeetCode解題報告 452. Minimum Number of Arrows to Burst Balloons [medium]

conniemessi發表於2016-12-18

題目描述

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軸上一定長度區域的位置,如果有交集就可以使用同一支箭。
使用貪心演算法,開始時第一支箭一定要在第一個氣球的範圍內,為了覆蓋儘可能多的別的氣球,假設箭在最左邊氣球的最右邊,依次向右遍歷氣球,當某個氣球(標記為*)的起點比箭所在位置(第一個氣球的最右邊)大的時候,需要多加一支箭,並且更新箭的位置為新氣球(標記為*的這個氣球)的最右邊。
演算法的關鍵在於對氣球的排序,以陣列的end值(最右邊)為基準,從小到大排序,而不是以start值(最左邊)為基準。這是因為有可能出現第二個氣球比第一個氣球的start大而end更小,如[1,10]和[3,6],這樣以來如果以左邊為基準排序,那麼第一個氣球為[1,10],箭在x=10處,就需要多加一支本不需要的箭來刺穿[3,6];正確的排序之後第一支箭應該在x=6處,這樣就能用一支刺破這兩個氣球了。

時間複雜度:

排序的複雜度為O(N*logN),貪心的複雜度為O(N),總複雜度為O(N*N*logN)。

程式碼如下:

class Solution {
public:
    static bool secondcompare(pair<int, int>&a, 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(), secondcompare);
        int sum=1;
        int bursting=points[0].second;
        for (int i=0; i<points.size(); i++) {
            if (points[i].first>bursting) {
                sum++;
                bursting=points[i].second;
            }
        }
        return sum;
    }
};



相關文章