演算法系列 · 第 24 關 · 解題招式

前綴和 Prefix Sum

先把累加和算好,之後查任何區間和都 O(1)。用空間換查詢速度。

前綴和的點子超簡單:先算好「從頭到每個位置的累加和」,之後要問「任意區間的和」,就用兩個前綴和相減,一次 O(1) 搞定,不用每次把區間重加一遍。建表花 O(n)、之後每次查詢 O(1) —— 查詢越多次越划算。

核心觀念

prefix[i] = arr 前 i 個的總和 —— 習慣讓 prefix[0]=0、prefix[i]=prefix[i-1]+arr[i-1]。

區間和公式 —— arr[l..r] 的和 = prefix[r+1] − prefix[l](大段減掉前面多算的那段)。

建一次、查無數次 —— 前處理 O(n),之後每次查詢 O(1)。

用空間換時間 —— 多存一個 n+1 大小的前綴陣列。

什麼時候用?

大量「區間和」查詢 —— 問很多次「l 到 r 的和」,前綴和完勝每次重加的 O(n)。

和為 k 的子陣列 —— 前綴和配雜湊表,把 O(n²) 壓到 O(n)(範例 3)。

差分陣列(反操作) —— 要「很多段區間各加值」,只動兩端、最後用前綴和還原(範例 8)。

二維版 —— 算任意子矩陣的和也能 O(1)(範例 6)。

複雜度

O(n)建前綴和表 —— 掃一遍累加,只做一次。
O(1)單次區間和查詢 —— 兩個前綴相減,一步到位。
O(n)空間 —— 多一個 n+1 的前綴陣列。
前綴和的精神是「把重複的加總只做一次」。如果你的程式一直在對「不同區間」重複求和,幾乎都能用前綴和加速。反過來,只查一兩次就沒必要建表。

用生活比喻它

🏃

里程碑記距離

記下「從起點到每根電線桿」的距離,任兩根之間的距離 = 相減就好。

💰

存摺累計餘額

每筆交易後的餘額都記著,某段期間的收支 = 期末餘額 − 期初餘額。

📈

累計票數

開票記「到第 N 箱為止的累計票」,某幾箱的票數 = 相減。

🎮 建前綴和 + O(1) 區間查詢

先由左往右建前綴和 prefix[i]=prefix[i-1]+arr[i-1](琥珀是相加的來源、紫色是新算出的)。建好後問「index 2 ~ 4 的區間和」,只要 prefix[5] − prefix[2](綠色兩格相減),O(1)!按「下一步」。

陣列 arr:
前綴和 prefix(prefix[i] = 前 i 個的和):

10 個程式碼範例(Python)

從建表 + 區間查詢、和為 k 的子陣列、樞紐索引、除自己以外的乘積,到二維前綴和、差分陣列、前綴 XOR。

顯示範例:

常見陷阱

❌ 前綴索引差一格 —— prefix[0]=0 的慣例下,arr[l..r] = prefix[r+1] − prefix[l];經典 off-by-one 雷。

❌ 只查一兩次還建表 —— 建表本身 O(n),查太少次不划算,直接加就好。

❌ 忘了 seen={0:1} 初始 —— 「和為 k」那類要先放一個空前綴,否則會漏掉「從頭開始」的子陣列。

❌ 一邊查一邊改陣列 —— 前綴和是「靜態」快照;資料會變動要用樹狀陣列 / 線段樹。

🎯 換你了(先別急著查答案)

把答案打到對話裡,我幫你對。