置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2026年7月6日 星期一

LeetCode 解題筆記:1288. Remove Covered Intervals

作者:王一哲
日期:2026年7月6日


LeetCode 題目連結:1288. Remove Covered Intervals

解題想法


中等難度題。題目給定數個區間 $intervals$,其中某些區間可以被其它區間覆蓋,假設移除掉被覆蓋的區間,回傳剩下的區間數量。題目給的提示是時間複雜度為 $O(n^2)$ 的寫法,用兩層 for 迴圈,逐一檢查某個區間是否可以被其它區間覆蓋,由於一個區間可能會被多個區間複蓋,還要用另一個陣列記錄被覆蓋的狀態,或是用一個集合記錄被覆蓋的區間。
這一題比較快的寫法是利用排序,將區間先依照起點由小到大排序,如果起點相同,再依照終點由大到小排序,這個步驟的時間複雜度為 $O(n \log n)$。定義目前已經出現的最大終點 max_end = 0,用一個 for 迴圈讀取排序後的區間,如果這個區間的終點 end <= max_end,代表這個區間可以被覆蓋,被覆蓋區間數量 removed 加 1;反之,更新 max_end 為 end;這個步驟的時間複雜度為 $O(n)$。速度會比前一個方法快很多。

Python 程式碼


Runtime: 271 ms, beats 5.08%. Memory: 19.65 MB, beats 47.88%.
class Solution:
    def removeCoveredIntervals(self, intervals) -> int:
        n = len(intervals)
        intervals.sort(key = lambda x : (x[1], -x[0]))
        removed = [False] * n
        for i in range(1, n):
            for j in range(0, i):
                if intervals[j][0] >= intervals[i][0]:
                    removed[j] = True
        return n - sum(removed[i] for i in range(n))

Runtime: 3 ms, beats 77.50%. Memory: 19.64 MB, beats 47.88%.
class Solution:
    def removeCoveredIntervals(self, intervals) -> int:
        n = len(intervals)  # 數量
        # 排序區間,起點遞增、終點遞減
        intervals.sort(key = lambda x : (x[0], -x[1]))
        removed = 0  # 移除的區間數量
        max_end = 0  # 目前已經出現過的最大終點
        for start, end in intervals:  # 各區間的起點、終點
            if max_end >= end:  # 目前的最大終點可以覆蓋這個區間
                removed += 1  # 數量加 1
            else:  # 反之,更新 max_end
                max_end = end
        return n - removed  # 回傳答案


C++ 程式碼


Runtime: 75 ms, beats 6.09%. Memory: 15.26 MB, beats 30.60%.
class Solution {
public:
    int removeCoveredIntervals(vector<vector<int>>& intervals) {
        int n = (int)intervals.size();
        vector<bool> removed (n, false);
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if (i == j) continue;
                if (intervals[i][0] <= intervals[j][0] && intervals[i][1] >= intervals[j][1]) {
                    removed[j] = true;
                }
            }
        }
        int tot = 0;
        for(int i = 0; i < n; i++) {
            if (removed[i]) tot++;
        }
        return n - tot;
    }
};

Runtime: 0 ms, beats 100.00%. Memory: 15.23 MB, beats 30.60%. 程式碼第 6 行的 lambda function 如果寫成底下這樣速度會很慢。
[](vector<int> a, vector<int> b) {

class Solution {
public:
    int removeCoveredIntervals(vector<vector<int>>& intervals) {
        int n = (int)intervals.size();  // 數量
        // 排序區間,起點遞增、終點遞減
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b) {
            if (a[0] == b[0]) return a[1] > b[1];
            return a[0] < b[0];
        } );
        int removed = 0, max_end = 0;  // 移除的區間數量,目前已經出現過的最大終點
        for(const auto& it : intervals) {  // 各區間的起點、終點
            if (max_end >= it[1]) {  // 目前的最大終點可以覆蓋這個區間
                removed++;  // 數量加 1
            } else {  // 反之,更新 max_end
                max_end = it[1];
            }
        }
        return n - removed;  // 回傳答案
    }
};


沒有留言:

張貼留言