具代表性的面試主題

如何實作 Skip List,並解釋它為何期望 O(log N)?

程式題困難
OfferCC 編輯團隊發佈 更新

題幹

請實作支援搜尋、插入、刪除與範圍遍歷的 Skip List。說明隨機層高如何替代平衡樹、最壞情況是什麼,以及如何處理重複鍵與並發讀寫。

1. 題目

你需要一個有序字典,支援按鍵搜尋、插入、刪除與範圍掃描。資料量會動態增長,面試官要求平均操作接近 O(log N),但不要求實作 AVL 或紅黑樹。請設計 Skip List 並分析隨機性、邊界與記憶體配置。

2. 約束與澄清

  • 明確鍵是否唯一;若重複,定義覆蓋、計數或穩定順序。
  • 設定最大層數與每層晉升機率 p,通常從底層鏈結串列開始向上建立索引。
  • 搜尋、插入與刪除需要維護每一層的前驅節點;範圍遍歷只需沿底層鏈結串列前進。
  • 先討論單執行緒結構;若要並發,需要額外的鎖、版本或無鎖演算法證明。

3. 核心思路

每個節點擁有高度隨機的 forward 指標陣列。搜尋從最高層頭節點開始:若下一個鍵仍小於目標,就沿目前層前進;否則下降一層。插入先記錄每層前驅,再隨機產生新高度並逐層接入。刪除同樣使用前驅陣列斷開指標。隨機層高讓高層節點稀疏,期望總指標數為 O(N),搜尋、插入與刪除的期望時間為 O(log N)。

4. 參考實作

text
randomLevel(rng, p, maxLevel):
  level = 1
  while level < maxLevel and rng.uniform01() < p:
    level += 1
  return level

findPredecessors(key):
  update = array(maxLevel)
  node = head
  for level from maxLevel - 1 down to 0:
    while node.forward[level] != nil and node.forward[level].key < key:
      node = node.forward[level]
    update[level] = node
  return update

insert(key, value):
  update = findPredecessors(key)
  if update[0].forward[0].key == key:
    update[0].forward[0].value = value
    return
  node = Node(key, value, randomLevel(rng, p, maxLevel))
  for level in 0 .. node.height - 1:
    node.forward[level] = update[level].forward[level]
    update[level].forward[level] = node

實作中必須先檢查 nil 再讀取鍵,並保證新節點高度不超過 maxLevel。刪除時把所有指向目標節點的層級一次接到後繼節點;最高層為空後可降低目前有效層數,但不必移動節點。

5. 複雜度與最壞情況

當晉升機率固定且隨機源獨立時,層數與路徑長度的期望為對數級,空間期望為 O(N)。隨機性失效或敵手能預測層高時,結構可能退化成單鏈結串列,操作變為 O(N)。可使用高品質隨機源、限制最大高度、定期重建或採用確定性平衡樹來處理對抗性工作負載。

6. 驗證與並發取捨

  • 用有序、重複、空結構與極端鍵測試搜尋、更新、刪除及範圍遍歷。
  • 統計不同 N 下的高度分布、平均路徑長度與指標數量,檢查是否符合預期。
  • 做隨機操作序列,與標準有序映射對拍,驗證內容和順序一致。
  • 並發版本要說明讀寫鎖粒度、刪除標記、記憶體回收與 ABA 風險;不能只把指標寫入包在一個鎖裡就宣稱無鎖安全。

7. 常見誤區

  • 只寫搜尋,不維護每層前驅,導致插入或刪除退化為重新掃描。
  • 忽略重複鍵策略,插入後範圍遍歷順序不穩定。
  • 把期望 O(log N) 當作最壞保證,未討論隨機源與對抗性輸入。
  • 使用固定高度陣列浪費記憶體,或允許高度無界導致陣列越界。

8. 面試評分點

能從高層向下搜尋

應說明每層前進條件、下降時機,以及為什麼底層鏈結串列包含全部元素。

能正確維護前驅

應在插入和刪除中保存各層 update 陣列,處理覆蓋、空指標與最高層收縮。

能解釋機率複雜度

應給出 O(log N) 期望時間、O(N) 期望空間和退化到 O(N) 的條件。

能識別並發邊界

應討論鎖、版本、標記刪除、記憶體回收與 ABA,而不是把單執行緒程式直接當作並發實作。

公開來源

同類題目

資源

產品比較

每份比較均依官方資料整理,並標示複核日期。

查看完整比較

相關面試工具

用 Screenshot 處理演算法題

截圖題目後,依序看約束、解法、程式碼、邊界條件和複雜度。

查看工具