leetcode 陣列專題 06-掃描線演算法(Sweep Line Algorithm)

老马啸西风發表於2024-11-15

掃描線專題

leetcode 陣列專題 06-掃描線演算法(Sweep Line Algorithm)

leetcode 陣列專題 06-leetcode.218 the-skyline-problem 力扣.218 天際線問題

leetcode 陣列專題 06-leetcode.252 meeting room 力扣.252 會議室

leetcode 陣列專題 06-leetcode.253 meeting room ii 力扣.253 會議室 II

什麼是掃描線演算法?

掃描線演算法(Sweep Line Algorithm)是一種常用於解決幾何問題(尤其是涉及區間、時間線或事件的重疊問題)的演算法。

它的基本思想是“模擬一條掃描線從一個方向掃過所有事件”,在掃描過程中維護一個資料結構來追蹤當前的狀態(例如活動區間的數量、最小值、最大值等)。

掃描線演算法的基本步驟

  1. 事件表示:每個問題中的區間(例如會議時間)或事件,都可以轉化為若干個關鍵事件(例如開始時間和結束時間)。

  2. 事件排序:將所有事件按照時間排序(如果時間相同,則根據事件的型別來排序,例如結束事件優先於開始事件)。

  3. 掃描過程:從最早的事件開始,按照排序順序逐一處理每個事件,並在處理每個事件時更新狀態(例如活動會議的數量、最大活動時間等)。

  4. 資料維護:根據事件型別,更新當前的活動狀態。例如,遇到一個開始事件時,我們增加一個計數,遇到結束事件時,減少計數,或者更新其他需要維護的值。

  5. 輸出結果:在掃描過程中,根據需求輸出解答。

應用場景

掃描線演算法廣泛應用於處理各種區間問題,典型的應用包括:

  • 會議安排(檢測會議時間是否有重疊)
  • 區間覆蓋問題(檢查是否有足夠的資源覆蓋所有區間)
  • 計算最大併發數(計算在某一時間點活躍的事件數量,如計算最多同時存在的會議數)
  • 凸包問題(計算一個點集的最小凸包)

掃描線演算法的具體步驟

1. 事件表示與排序

假設我們有若干個區間(如會議的開始時間和結束時間),我們首先將每個區間拆解為兩個事件:

一個是開始事件,另一個是結束事件。

每個事件可以表示為一個元組 (time, type),其中 time 表示事件發生的時間,type 可以是 +1(表示開始)或者 -1(表示結束)。

例如,會議區間 [(5, 10), (8, 12), (13, 16)] 可以拆解為事件:

[(5, +1), (10, -1), (8, +1), (12, -1), (13, +1), (16, -1)]

事件按時間排序。如果有多個事件發生在相同的時間點,則優先處理結束事件,因為結束事件可以使得下一個開始事件得以處理。

2. 事件掃描與狀態更新

掃描線的核心是對事件的處理。在掃描線遍歷時,我們保持一個計數器(或其他資料結構)來跟蹤當前的活動狀態。對於會議安排問題,我們使用一個計數器來記錄當前同時進行的會議數量。

  • 當遇到一個 開始事件+1),增加計數器,表示新的會議開始。
  • 當遇到一個 結束事件-1),減少計數器,表示一個會議結束。

3. 結果輸出

在掃描過程中,我們可以輸出每個時間點的活動狀態。例如,我們可以在每次更新計數器時,檢查當前同時進行的會議數,或者記錄最大會議數等。

例子:檢測會議是否有重疊

假設我們有一組會議的時間區間,使用掃描線演算法來判斷是否所有會議都能參加。

給定的會議區間:[[0, 30], [5, 10], [15, 20]]

1. 拆解事件

我們將每個會議區間拆解成開始事件和結束事件:

[(0, +1), (30, -1), (5, +1), (10, -1), (15, +1), (20, -1)]

2. 事件排序

按時間排序事件,時間相同的情況下優先處理結束事件:

[(0, +1), (5, +1), (10, -1), (15, +1), (20, -1), (30, -1)]

3. 掃描事件並更新狀態

我們從第一個事件開始,逐一掃描:

  • 在時間 0 處,遇到開始事件 +1,活動會議數增加到 1。
  • 在時間 5 處,遇到開始事件 +1,活動會議數增加到 2,說明此時有兩個會議重疊。
  • 在時間 10 處,遇到結束事件 -1,活動會議數減少到 1。
  • 在時間 15 處,遇到開始事件 +1,活動會議數增加到 2,說明此時又有兩個會議重疊。
  • 在時間 20 處,遇到結束事件 -1,活動會議數減少到 1。
  • 在時間 30 處,遇到結束事件 -1,活動會議數減少到 0。

4. 判斷是否有重疊

在掃描過程中,我們發現活動會議數有過大於 1 的情況(特別是在時間 5 和時間 15),因此有重疊會議,返回 false

掃描線演算法的優勢

  1. 時間複雜度:事件排序的時間複雜度是 O(n log n),其中 n 是會議數或事件數。掃描線的遍歷時間複雜度是 O(n)。因此,整體時間複雜度是 O(n log n),比暴力演算法(O(n^2))要高效得多。

  2. 空間複雜度:需要儲存所有事件,空間複雜度為 O(n)

  3. 易於擴充套件:掃描線演算法可以很容易地適應更多的需求,例如統計某一時刻活動的最大數量、求得活動的區間並進行其他計算等。

擴充套件應用

  • 最大併發活動數:透過掃描線演算法,我們可以輕鬆地計算在某個時刻同時進行的最多會議數(即最大併發數)。
  • 區間合併:我們還可以透過掃描線演算法來合併重疊的區間。
  • 區間覆蓋:檢查一組區間是否能完全覆蓋一個目標區間等。

總結

掃描線演算法是一種非常強大且高效的演算法,尤其適用於處理與區間重疊、事件排序相關的幾何問題。

在許多情況下,它比暴力演算法要高效得多,尤其是在資料量大的時候,能夠顯著減少計算的複雜度。

參考資料

https://leetcode.cn/problems/4sum/

相關文章