快轉到主要內容
  1. Algorithms/

Difference Array

·1 分鐘· ·
Blog Algorithm Difference Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

介紹
#

差分陣列(Difference Array)是一種常用於「區間更新」問題的演算法技巧。
當題目要求對一個範圍內的數值進行修改時,
與其每次修改整個區間,不如只記錄起點與終點的變化
之後再透過**前綴和(Prefix Sum)**從左到右累加,還原出更新後的完整陣列。

核心概念
#

origin = [1, 3, 2]
k = 5
operations = [[0, 1, 1], [1, 2, -1], [0, 2, 1]]

for start, end, amount in operations:
    for idx in range(start, end + 1):
        origin[idx] += amount

return max(origin) <= k

這是 O(n * m) 的操作(其中 n 是陣列長度,m 是操作數量)。

但如果使用差分陣列技巧,就可以避免內層迴圈,
只需在特定位置記錄變化,再透過前綴和還原結果:

difference_array = [0] * (len(origin) + 1)

for start, end, amount in operations:
    difference_array[start] += amount
    difference_array[end + 1] -= amount

diff = 0
for i in range(len(origin)):
    diff += difference_array[i]
    status = origin[i] + diff
    if status >= k:
        return False

return True

這樣可以將時間複雜度降到 O(n + m)

模板
#

1. Initialization

difference_array = [0] * (len(nums) + 1)

開一個比原本陣列長度多 1 的差分陣列,用來標記每個位置的增減變化。

2. Apply operations

for start, end, amount in operations:
    difference_array[start] += amount
    difference_array[end + 1] -= amount

只在 start 增加,在 end + 1 減少,代表一段區間內的累積變化。

3. Prefix sum to recover the final state

result = []
diff = 0
for i in range(len(nums)):
    diff += difference_array[i]
    result.append(nums[i] + diff)

不知道nums的長度
#

如果我們不知道 nums 的長度,
例如題目只提供了操作(operations),
我們可以使用哈希表(hash map)來記錄每個索引位置的差分變化量。
之後,根據 hash map 的
鍵(索引)排序

依照排序後的索引進行前綴和累加,來還原出最終的結果。

diff_map = default_dict(int)
for start, end, amount in differences:
    diff_map[start] += 1
    diff_map[end+1] -=1

diff = 0
for key in sorted(diff_map.keys()):
    diff += diff_map[key]

主要參數說明:
#

範例
#

LeetCode
#

相關文章

Prefix Sum
·1 分鐘
Blog Algorithm Prefix Sum
Prefix Sum 介紹
Next Permutation
·1 分鐘
Blog Algorithm Next Permutation
Next Permutation 介紹
Digit Dynamic Programming
·2 分鐘
Blog Algorithm Digit DP
Digit Dynamic Programming 介紹
LeetCode 1094: Car Pooling
·1 分鐘
LeetCode Difference Array Medium
LeetCode 解題紀錄
LeetCode 1109: Corporate Flight Bookings
·1 分鐘
LeetCode Difference Array Medium
LeetCode 解題紀錄
LeetCode 2381: Shifting Letters II
·1 分鐘
LeetCode Medium Difference Array
LeetCode 解題紀錄