1.題目介紹
題目地址(452. 用最少數量的箭引爆氣球 - 力扣(LeetCode))
https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/
題目描述
有一些球形氣球貼在一堵用 XY 平面表示的牆面上。牆面上的氣球記錄在整數陣列 points
,其中points[i] = [xstart, xend]
表示水平直徑在 xstart
和 xend
之間的氣球。你不知道氣球的確切 y 座標。
一支弓箭可以沿著 x 軸從不同點 完全垂直 地射出。在座標 x
處射出一支箭,若有一個氣球的直徑的開始和結束座標為 x
start
,x
end
, 且滿足 xstart ≤ x ≤ x
end
,則該氣球會被 引爆 。可以射出的弓箭的數量 沒有限制 。 弓箭一旦被射出之後,可以無限地前進。
給你一個陣列 points
,返回引爆所有氣球所必須射出的 最小 弓箭數 。
示例 1:
輸入:points = [[10,16],[2,8],[1,6],[7,12]] 輸出:2 解釋:氣球可以用2支箭來爆破: -在x = 6處射出箭,擊破氣球[2,8]和[1,6]。 -在x = 11處發射箭,擊破氣球[10,16]和[7,12]。
示例 2:
輸入:points = [[1,2],[3,4],[5,6],[7,8]] 輸出:4 解釋:每個氣球需要射出一支箭,總共需要4支箭。
示例 3:
輸入:points = [[1,2],[2,3],[3,4],[4,5]] 輸出:2 解釋:氣球可以用2支箭來爆破: - 在x = 2處發射箭,擊破氣球[1,2]和[2,3]。 - 在x = 4處射出箭,擊破氣球[3,4]和[4,5]。
提示:
1 <= points.length <= 105
points[i].length == 2
-231 <= xstart < xend <= 231 - 1
2.題解
2.1 貪心演算法
思路
看了這個圖,我就瞬間明白這題的考點了。
這裡我們還是考慮幾種貪心策略:
1.最小右邊界x_r
2.最大左邊界x_l
3.區間最短的邊界
我們如果想要一支箭貫穿最多的氣球,首先考慮木桶效應,因為我們知道區間長度較長的氣球,可以相容移動更長的射箭範圍,而真正限制我們的是那些較短的區間的氣球
我們還是從左到右遍歷,我們將射箭點從左往右移動的時候,貫穿的氣球數越來越多,直到一個極限點,到大最小右邊界的氣球右邊界,再往右這個氣球便無法貫穿,
我們不可能繼續向右移動,這樣我們就要單獨射出一支箭只為了解決這一個氣球;我們最好的選擇是在此射箭,選擇當前步驟的最優解,並準備下一次射箭(去除已經射爆的氣球)
程式碼
- 語言支援:C++
C++ Code:
class Solution {
public:
static bool compare(vector<int> p1, vector<int> p2){
return p1[1] < p2[1];
}
int findMinArrowShots(vector<vector<int>>& points) {
sort(points.begin(), points.end(), compare);
int i = 0, cnt = 0;
while(i < points.size()){
cnt++;
int rLen = points[i][1];
while(++i < points.size() && points[i][0] <= rLen){}
}
return cnt;
}
};
複雜度分析
令 n 為陣列長度。
- 時間複雜度:\(O(n)\)
- 空間複雜度:\(O(n)\)