橫軸是時間,bar疊到一起就要併。
「目前這條」和「前面已經合併好的最後一條」。
例如:目前合併結果:[1,3];下一條:[2,6];
因為:下一條 start = 2;目前 end = 3;2 <= 3
表Gantt上有碰到/重疊,所以延長右端:
[1,3] + [2,6]→ [1,6]
再看:目前:[1,6]下一條:[8,10];8 > 6
中間斷掉,所以不能合併,直接新增 [8,10]。
按左端排→從左往右只掃一次→下一條碰得到目前右端就延長,碰不到就開新的一段。
時間:排序:O(n log n)
掃一次:O(n)總共:O(n log n)
如果題目一開始就保證已按 start 排好,那甚至只需要掃一次:O(n)。
Input:[[1,3],[2,6],[8,10]]
Output:[[1,6],[8,10]]
[1,3] 和 [2,6] 重疊→ 合成 [1,6]
[8,10] 沒有跟 [1,6] 重疊→ 留下來
不能安全早停。
例如目前已經:[1,10]後面還有:[8,100]仍必須讀,因為答案要從:[1,10]變[1,100]甚至後面還可能有:[200,300]也必放進答案。
所以每個interval至少要看一次;真正花最多時間的是:sort(...)
一般未排序輸入下,在 comparison-based sorting(比較式排序)的模型裡,O(n log n) 最優標準解。
Sort→read往前掃→write留最後合併結果→overlap就延長,不overlap就寫下一格。
這比剛才另外建立 answer更符合你「不做多餘工作」的原則。
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {//併所有重疊區間
sort(intervals.begin(), intervals.end());//依start由小到大排序
int write = 0;//最後一個已合併區間的位置
for (int read = 1; read < intervals.size(); ++read) {//每個區間只讀一次
if (intervals[read][0] <= intervals[write][1]) {//下一段開始<=目前結尾表重疊
intervals[write][1] = max(intervals[write][1], intervals[read][1]); //只更新較遠的end
} else {//下一段完全分離
++write;
intervals[write] = intervals[read];//把新區間放進答案區域
}
}
intervals.resize(write + 1);//刪掉後面已經不用的區間
return intervals;//回傳合併完成的結果
}
};
write =「目前合併後的最後一格放在哪個 index」。
例如排序後:
intervals =
index 0: [1,3]
index 1: [2,6]
index 2: [8,10]
一開始:int write = 0;目前答案區只有:index 0: [1,3]所以 write = 0 指向它。
接著看到 [2,6],有重疊,就直接改:intervals[0] = [1,6]
write 還是 0,因為目前答案還是只有一段。
再看到 [8,10],不重疊:++write;變成:write = 1
然後:intervals[1] = [8,10];
最後答案區就是:
index 0: [1,6]
index 1: [8,10]
read = 現在正在看哪一段;write = 合併後答案目前寫到哪一格。
resize(write + 1) 本身就是把 vector 的「有效長度」縮短,超過新長度的元素會被移除。
intervals =
index 0: [1,6]
index 1: [8,10]
index 2: [8,10] ← 舊資料
index 3: [15,18] ← 舊資料
write = 1表真正答案只到 index 1,也就是前 2 格。
intervals.resize(write + 1);
intervals.resize(2);
become index 0: [1,6];index 1: [8,10]後面的 index 2、3 就被 vector 移除了。
resize(2) = 把 vector 長度改成 2,所以只保留 index 0、1
7.write存的是最後一個答案的index,resize()要的是總共有幾個元素。
例如:write = 0代表最後答案在 index 0,所以其實有:1 個元素
因此:resize(write + 1); // resize(1)
再例如:write = 2
代表答案放到:
index 0;index 1;index 2總共有 3 個元素,
resize(write + 1); // resize(3)
index 從 0 開始,所以「最後 index + 1 = 元素個數」。