English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

nu

guest
1 / ?
back to lessons

最佳、最差和平均情況

衡量算法的三種方式

每個算法的代價取決於其輸入。相同大小的兩個輸入可能會產生截然不同的運行時間。複雜度分析形式化了三種看待這種變化的視角。

Big O 增長形狀:O(1) 平坦,O(log N) 曲線,O(N) 對角線,O(N²) 拋物線


最佳情況 — Ω (Omega): 使算法完成最快的輸入。對於線性搜索一個 N 項的列表:Ω(1) — 目標佔據第一個位置。一次比較,完成。


最差情況 — O (Big O): 使算法完成最慢的輸入。對於線性搜索:O(N) — 目標位於列表的最後,或根本不出現。每個元素都需要檢查。


平均情況 — Θ (Theta): 假設均勻分佈,所有可能輸入上的預期成本。對於線性搜索,目標等可能地佔據任意 N 個位置之一:Θ(N/2) = Θ(N)。常數 1/2 被丟棄,因為 Theta 表示緊漸近增長,而不是精確係數。


為什麼最差情況佔主導

系統必須處理最差情況。平均耗時 10 毫秒但偶爾需要 60 秒的數據庫查詢會產生用戶可見的故障。工程師為最差情況界限設計,以便無論輸入如何,性能都保持可預測。平均情況分析在概率設置中有價值,但最差情況分析提供保證。

二分搜索情況分析

二分搜索只能在排序數組上工作。在每一步:將目標與中點處的元素進行比較。如果目標等於中點,返回它。如果目標更小,在左半邊遞歸。如果更大,在右半邊遞歸。


每次比較都消除了剩餘候選者的一半。

對於 N 個元素的排序數組上的二分搜索:(a) 給出最佳情況複雜度並描述達到它的輸入;(b) 給出最差情況複雜度並解釋為什麼是 O(log N);(c) 解釋為什麼二分搜索的平均情況複雜度等於最差情況複雜度。

記憶體增長和時空權衡

計數記憶體,而不是操作

時間複雜度衡量算法執行的操作數。空間複雜度衡量它在輸入之外分配的額外記憶體。這兩者在生產系統中都很重要:一個快速算法如果分配 O(N²) 記憶體將耗盡服務器資源。


O(1) 空間: 常數額外記憶體,與 N 無關。原地排序(例如插入排序)在原始數組內交換元素。它使用幾個臨時變數 — O(1),無論數組多大。


O(N) 空間: 記憶體與輸入大小成正比。創建一個 N 元素數組的副本需要 N 個插槽。從 N 個字符串的列表構建哈希集合最多存儲 N 個條目。


O(N²) 空間: 記憶體與 N² 成正比。為具有 N 個頂點的圖構建一個 N×N 鄰接矩陣需要 N² 個單元。在 N = 10,000 個頂點時,這是 10^8 個條目 — 一個簡單布爾網格需要數百兆字節。


時空權衡

算法設計中的基本動作之一:用空間換取時間,或用時間換取空間。


哈希表使用 O(N) 額外空間來實現 O(1) 查找。沒有哈希表,掃描列表實現 O(N) 查找,只需要 O(1) 額外空間。哈希表花費記憶體來購買速度。


記憶化存儲先前計算的結果(O(N) 或更多空間)以避免重新計算。沒有記憶化的遞歸斐波那契運行時間為 O(2^N)。有記憶化:O(N) 時間和 O(N) 空間。空間投資指數級縮小時間。

哈希字典與排序列表

比較在 N 個單詞的文檔中計數單詞出現次數的兩種策略:


策略 A: 一個字典(哈希映射)。插入每個單詞;增加其計數。


策略 B: 維護已看到的單詞的排序列表;使用二分搜索在插入前檢查成員資格。

一個算法處理 N 個字符串的列表,並使用字典計數每個唯一字符串的出現次數。(a) 給出構建字典的時間複雜度。(b) 給出空間複雜度。(c) 如果算法改為使用帶二分搜索的排序列表來檢查重複項,時間和空間複雜度是什麼?哪種方法用空間換取時間?

攤銷分析:分散成本

當偶爾的開銷不會破壞平均性能時

有些操作偶爾很昂貴,但在序列中平均成本較低。攤銷分析計算整個序列上每個操作的 平均 成本 — 而不是單個操作的最差情況成本。


動態數組(Python 列表、Java ArrayList): 以容量 1 開始。滿時,容量加倍。加倍複製所有現有元素:一個附加需要 O(N) 工作。但加倍很少見。在 N 個總附加後,發生了多少總複製操作?


攤銷 O(1):動態數組加倍將總複製成本分散在 N 個插入中

加倍發生在大小 1、2、4、8、...、N/2。複製計數:1 + 2 + 4 + ... + N/2。這是一個幾何級數,在所有 N 個附加中總計為 N − 1 次複製。每個附加的平均複製:(N − 1) / N < 1,所以 O(1) 攤銷每附加 儘管每次加倍有 O(N) 最差情況成本。


為什麼攤銷分析很重要

一個偶爾暫停以調整大小、重新平衡或壓縮結構的系統可能看起來有驚人的最差情況單個操作。攤銷分析揭示了這個警告是錯誤的:罕見的昂貴事件由許多便宜的事件支付。理解攤銷成本可以防止過度設計:為避免罕見的 O(N) 操作而增加複雜性(只貢獻 O(1) 攤銷)是浪費的工作。


更深入: unhamming 課程將複雜度分析應用於生產軟件中的實際缺陷。見 缺失的章節:算法複雜度 & MOAD-0001:沉積缺陷

哈希表攤銷插入

哈希表從空開始,當負載因子超過 0.75 時容量加倍。插入 1,000 個元素在容量 1、2、4、8、16、32、64、128、256、512 時恰好觸發 10 次加倍。

分析這個哈希表的攤銷插入成本。(a) 單個插入的最差情況時間是什麼(當它觸發加倍時)?(b) 計算所有 10 次加倍中的總複製工作。(c) 所有 1,000 個插入中每個插入的攤銷成本是什麼?