
題目解析: 給定一堆氣球在 X 軸上的起點與終點,從底下往上射箭,只要氣球的範圍有涵蓋到射箭的 X 座標就會爆掉,求最少需要幾支箭才能射爆所有氣球。
解題思路: 這題用貪婪演算法。先寫一個排序規則 cmp,把氣球依照「結束位置」由小到大排好。設變數 ans 為 1(至少要一支箭),變數 q 記住目前第一顆氣球的結束位置。接著丟進迴圈從第二顆開始看,如果下一顆氣球的起點大於 q,代表上一支箭射不到這顆,所以 ans 加 1,並把 q 更新為新氣球的結束位置。最後回傳 ans。
class Solution {
public:
static bool cmp(vector<int>& a, vector<int>& b) {
return a[1] < b[1];
}
int findMinArrowShots(vector<vector<int>>& points) {
if (points.empty()) return 0;
sort(points.begin(), points.end(), cmp);
int ans = 1;
int q = points[0][1];
for (int i = 1; i < points.size(); i++) {
if (points[i][0] > q) {
ans++;
q = points[i][1];
}
}
return ans;
}
};

題目解析: 給定多個區間,找出最少需要移除幾個區間,才能讓剩下的區間完全不重疊(邊界剛好相連不算重疊)。
解題思路: 這題的邏輯跟射氣球非常像!一樣先把區間照「結束位置」由小到大排序。設 ans 為 0 來記錄要移除的數量,變數 q 記錄目前區間的結束位置。丟進迴圈從第二個區間開始跑,如果這個區間的起點小於 q,代表重疊了必須拔掉,把 ans 加 1;如果沒有重疊,就把 q 更新為這個新區間的結束位置,繼續往下比對。迴圈跑完回傳 ans 即可。
class Solution {
public:
static bool cmp(vector<int>& a, vector<int>& b) {
return a[1] < b[1];
}
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if (intervals.empty()) return 0;
sort(intervals.begin(), intervals.end(), cmp);
int ans = 0;
int q = intervals[0][1];
for (int i = 1; i < intervals.size(); i++) {
if (intervals[i][0] < q) {
ans++;
} else {
q = intervals[i][1];
}
}
return ans;
}
};