閱讀代碼以理解增長率
正確性代碼審查 vs 複雜性代碼審查
正確性審查捕捉邏輯錯誤:錯誤的條件、邊界索引錯誤、缺少空指針檢查。複雜性感知審查捕捉另一類缺陷:代碼在 N = 100 時正確運行,但在 N = 100,000 時增長災難性。
本課程連接至更深入的調查(unhamming 課程):遺失的章節:算法複雜性 從生產缺陷的背景講解 Big O,而 MOAD-0001:沉積式缺陷 在 60+ 個軟件生態系統中映射該模式。
兩個審查啟發式方法
嵌套循環相乘複雜性。 兩個 N 項嵌套循環產生 O(N²)。三個產生 O(N³)。審查時:首先計算循環嵌套深度。
熱循環中的順序容器。 任何 .contains()、.includes()、.find() 或 in list 檢查在循環內的成本為 O(N) 每次檢查。迭代 N 次:O(N²) 總計。此模式出現在許多生態系統的生產代碼中——GHC Haskell 編譯器、Python pip、Apache Maven、Rust Cargo、TypeScript、Godot。相同的錯誤,不同的代碼庫。
審查:find_duplicates
審查以下 Python 函數的複雜性:
def find_duplicates(items):
seen = []
duplicates = []
for item in items:
if item in seen:
duplicates.append(item)
else:
seen.append(item)
return duplicates
MOAD-0001:沉積式缺陷
相同的缺陷,六十個生態系統
模式 if x not in list: list.append(x) 在循環內出現——已出現——在許多軟件生態系統的生產代碼中:
- GHC(Haskell 編譯器):依賴解析器,O(N²) 在 N = 50,000 個包,17 分鐘構建
- Python pip:依賴衝突解決
- Apache Maven:類路徑重複數據刪除
- Rust Cargo:功能統一
- TypeScript 編譯器:模塊解析
- Godot / Redot 遊戲引擎:節點圖遍歷
這些團隊都沒有犯錯誤。他們在小 N 時編寫了正確的代碼。N 增長。代碼硬化了。該模式有一個名字:MOAD-0001,沉積式缺陷。 沉積物:正確的,在薄層中無害。隨著時間推移,層積累並硬化。
修復
在每種情況下:用哈希容器替換順序容器。一行。對正確輸入的零行為改變。在真實世界的 N 下 100–1,000× 加速。
修復之所以有效,是因為兩個操作需要保持快速:
1. 成員資格檢查: 該元素是否已被看到?
2. 有序輸出: 返回元素在出現時的順序(有時需要,有時不需要)。
集合在 O(1) 中處理 (1)。如果 (2) 也重要,請維護一個單獨的有序輸出列表和一個用於成員資格檢查的集合。兩個數據結構,每個執行一個工作。
回應審查員
拉取請求在項目的圖形遍歷函數中修復 MOAD-0001。審查員評論:
> "集合不保留插入順序——這改變了行為。"
面試分析模式
預期格式
算法複雜性分析出現在軟件工程面試中。強有力的答案遵循四部分模式:
1. 陳述當前複雜性——時間 O(?),空間 O(?)。
2. 解釋為什麼——確定負責的具體構造(嵌套循環、循環內線性掃描、遞歸分支)。
3. 提出優化——命名更改及其引入的數據結構或算法。
4. 陳述新複雜性——修復後,時間和空間複雜性是什麼?
例子:
代碼:[在循環內檢查列表中成員資格的函數]
當前:O(N²) — `item in seen_list` 是 O(N) 每次檢查 × N 次迭代
優化:用 seen_set(哈希集)替換 seen_list
之後:O(N) — 集合成員資格檢查是 O(1)
此技能傳遞到面試之外:複雜性感知代碼審查、架構設計、性能調試、安全審計。任何處理可變大小輸入的系統都受益於它。
本課程向前連接到 unhamming 課程,該課程將此確切的模式應用於 60+ 開源項目的生產缺陷調查。
面試:分析 has_common_element
將四部分面試格式應用於此函數:
def has_common_element(list_a, list_b):
for item in list_a:
for other in list_b:
if item == other:
return True
return False