2020_11_23 每日一題 452. 用最少數量的箭引爆氣球

鹹魚極光發表於2020-11-23

在二維空間中有許多球形的氣球。對於每個氣球,提供的輸入是水平方向上,氣球直徑的開始和結束座標。由於它是水平的,所以縱座標並不重要,因此只要知道開始和結束的橫座標就足夠了。開始座標總是小於結束座標。

一支弓箭可以沿著 x 軸從不同點完全垂直地射出。在座標 x 處射出一支箭,若有一個氣球的直徑的開始和結束座標為 xstart,xend,
且滿足 xstart ≤ x ≤ xend,則該氣球會被引爆。可以射出的弓箭的數量沒有限制。
弓箭一旦被射出之後,可以無限地前進。我們想找到使得所有氣球全部被引爆,所需的弓箭的最小數量。

給你一個陣列 points ,其中 points [i] = [xstart,xend] ,返回引爆所有氣球所必須射出的最小弓箭數。

示例 1:

輸入:points = [[10,16],[2,8],[1,6],[7,12]]

輸出:2

解釋:對於該樣例,x = 6 可以射爆 [2,8],[1,6] 兩個氣球,以及 x = 11 射爆另外兩個氣球

示例 2:

輸入:points = [[1,2],[3,4],[5,6],[7,8]]

輸出:4

示例 3:

輸入:points = [[1,2],[2,3],[3,4],[4,5]]

輸出:2

示例 4:

輸入:points = [[1,2]]

輸出:1

示例 5:

輸入:points = [[2,3],[2,3]]

輸出:1

提示:

0 <= points.length <= 104

points[i].length == 2

-231 <= xstart < xend <= 231 - 1

來源:力扣(LeetCode)

連結:https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons

著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

其實是區間覆蓋的問題套了個射氣球的殼子
貪心地想,如果我有一種射箭地方案是最優,那麼把該方案的所有箭往右移到某氣球邊緣,也是最優方案。
所以我們先將氣球按左端點升序排序,排序後把第一個氣球右端點設為當前射箭的位置
前進的方式為:
如果下一個氣球左端點在當前箭位置左邊,那麼新氣球不用額外的箭來扎。但是如果新氣球的右端點在當前箭位置左邊,那麼當前射箭的位置需要左移至新氣球的右端點
如果新氣球的左端點大於當前箭的位置,那麼需要多射一箭(對於之前射出的箭想覆蓋這個氣球需要右移,但是之前的任何一箭右移都會造成有的氣球打不破,需要新加箭,沒啥意思)。多射一箭之後把新氣球的右端設為當前箭的位置
正確性證明似乎不太嚴謹TAT
程式碼:

class Solution {
    public int findMinArrowShots(int[][] points) {
        if(points.length == 0) {
            return 0;
        }
        Arrays.sort(points, (a, b) -> {
            if(a[0] != b[0]) {
                return ((long)a[0] - b[0]) > 0l ? 1 : -1;
            } else {
                return 0;
            }
        });

        int r = points[0][1];
        int ret = 1;
        for(int i = 1; i < points.length; ++i) {
            if(points[i][0] <= r) {
                r = Math.min(r, points[i][1]);
            } else {
                ++ret;
                r = points[i][1];
            }
        }
        return ret;
    }
}

相關文章