題目描述
給定長度為 n 的陣列(初始值全為 0),以及 k 個更新操作,每個操作為 [startIndex, endIndex, inc],代表將陣列索引 [startIndex, endIndex] 的所有元素都加上 inc。
完成所有操作後,回傳最終陣列。
範例:n=5, operations = [[1,3,2],[2,4,3],[0,2,-2]]
- 初始:[0, 0, 0, 0, 0]
- [1,3,2]:[0, 2, 2, 2, 0]
- [2,4,3]:[0, 2, 5, 5, 3]
- [0,2,-2]:[-2, 0, 3, 5, 3]
解題思路
核心思路:差分陣列(Difference Array)
暴力解法是對每個操作遍歷 [startIndex, endIndex] 並逐一更新,時間複雜度 O(n × k),效率低。
差分陣列是處理「區間批量修改」的經典技巧,時間複雜度降至 O(n + k):
定義差分陣列 diff[i] = result[i] - result[i-1](result[-1] = 0)。對區間 [l, r] 加 val 等價於:
diff[l] += val(從 l 開始增加)
diff[r+1] -= val(在 r+1 處撤銷增加)
最後對差分陣列做前綴和還原,即可得到最終結果:
result[i] = diff[0] + diff[1] + ... + diff[i]
為什麼差分陣列有效?
每個操作只修改兩個位置(O(1)),而不是整個區間(O(n))。k 個操作後,前綴和一次性還原所有修改。
直觀理解:diff[l] += val 代表「從 l 開始,後綴全部加 val」,diff[r+1] -= val 代表「從 r+1 開始,後綴全部減 val」,兩者疊加效果恰好是「區間 [l,r] 加 val」。
替代方案
方案一:暴力逐元素更新
對每個操作 [l, r, val],用迴圈將 result[l] 到 result[r] 都加上 val。
- 優點:實作極為簡單,無需理解差分陣列。
- 缺點:時間複雜度 O(n × k),當 n 和 k 都很大時(如 n=100000, k=100000)效率完全不可接受。
方案二:線段樹(Lazy Propagation)
使用帶懶惰標記的線段樹,支援 O(log n) 的區間更新和 O(log n) 的點查詢。
- 優點:若需要在操作過程中即時查詢某個位置的值,線段樹非常適合;適合在線(online)處理。
- 缺點:對於本題(所有操作先批量進行,再一次輸出全部結果)屬於過度設計,程式碼複雜度高,常數因子大;差分陣列的 O(n + k) 整體更優。
方案三:二元索引樹(Fenwick Tree)
支援區間加法和前綴和查詢,利用兩個 BIT 可以實作 O(log n) 的區間修改和 O(log n) 的單點查詢。
- 優點:比線段樹程式碼略短,支援動態查詢。
- 缺點:同樣對本題屬於過度設計,差分陣列方案已是最佳選擇。