題目描述:
在二維空間中有許多球形的氣球。對于每個氣球,提供的輸入是水平方向上,氣球直徑的開始和結束坐標。由于它是水平的,所以縱坐標并不重要,因此只要知道開始和結束的橫坐標就足夠了。開始坐標總是小于結束坐標。
一支弓箭可以沿著 x 軸從不同點完全垂直地射出。在坐標 x 處射出一支箭,若有一個氣球的直徑的開始和結束坐標為 xstart,xend, 且滿足 xstart ≤ x ≤ xend,則該氣球會被引爆??梢陨涑龅墓臄?shù)量沒有限制。 弓箭一旦被射出之后,可以無限地前進。我們想找到使得所有氣球全部被引爆,所需的弓箭的最小數(shù)量。
給你一個數(shù)組 points ,其中 points [i] = [xstart,xend] ,返回引爆所有氣球所必須射出的最小弓箭數(shù)。
示例 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
思路:
- 先對 points 進行排序,排序的規(guī)則是結束的縱坐標按照從小到大排列。
- 從points中的第一組開始,計算是否存在橫坐標重疊,如果出現(xiàn)重疊的部分則這個 point (氣球)不需要額外的弓箭既可以被戳破。最開始只有一個區(qū)間的時候自然不會存在重疊的現(xiàn)象,設置變量 a 來儲存該數(shù)據的結束橫坐標。
- 然后再遍歷第二個 point,可以想象第二個數(shù)據的結束橫坐標的值一定是大于前一個的結束橫坐標。于是可以分兩種情況:
a) 如果第二個數(shù)據的開始橫坐標大于 a,那么說明這兩個氣球的橫坐標無交集,需要另外的弓箭才能戳破,于是所需的弓箭數(shù)增加,而 a 的值也更新為這個point(氣球)的結束橫坐標。
b) 如果第二個數(shù)據的開始橫坐標小于或者等于 a,那么說明這兩個氣球的橫坐標有交集,不需要另外的弓箭就能戳破。 - 重復遍歷直至所有的 point都被遍歷。
代碼(C):
int findMinArrowShots(vector<vector<int>>& points) {
if (points.empty()) {
return 0;
}
sort(points.begin(), points.end(), [](const vector<int>& u, const vector<int>& v) {
return u[1] < v[1];
});
int pos = points[0][1];
int ans = 1;
for (const vector<int>& balloon: points) {
if (balloon[0] > pos) {
pos = balloon[1];
++ans;
}
}
return ans;
}