最大子數組問題
最大子數組問題(Maximum Subarray Problem)是一個著名的動態規劃問題,它的目標是在一個給定的數組中找到連續子數組,其總和最大。這個問題有多種變體,包括尋找最大連續子數組和最大非降子數組等。
這裡我們以尋找最大連續子數組為例來解釋這個問題。給定一個數組A
,我們需要找到一個連續子數組A[i..j]
,使得sum(A[i..j])
最大。如果數組A
的元素為a1, a2, ..., an
,則最大連續子數組問題可以表述為找到一個子數組a[i..j]
,使得sum(a[i..j]) = sum(a[i] + a[i+1] + ... + a[j])
最大。
動態規劃解決這個問題的算法如下:
-
設
f[i]
表示以A[i]
為最後一個元素的最大子數組和,那麼f[i]
可以由f[i-1]
擴展得到,因為我們只需要決定A[i]
是否屬於我們的最大子數組。 -
如果
A[i-1]
屬於最大子數組,那麼f[i]
等於A[i]
加上f[i-1]
,因為A[i-1]
已經是f[i-1]
的一部分,我們只需要加上A[i]
。如果A[i-1]
不屬於最大子數組,那麼f[i]
等於A[i]
加上f[i-2]
,因為f[i-2]
是沒有A[i-1]
的最大子數組和。 -
初始條件是
f[0] = A[0]
,因為以A[0]
為最後一個元素的最大子數組就是A[0]
本身。 -
我們從
i = 1
到n-1
更新f[i]
,最後f[n-1]
就是我們的最大子數組和。
這裡是動態規劃算法的Python實現:
def maxSubArray(A):
n = len(A)
f = [float('-inf')] * n # 初始化f數組,每個元素都為負無窮大
f[0] = A[0] # 初始化第一個元素
for i in range(1, n):
f[i] = max(A[i], A[i] + f[i-1]) # 更新f[i]
return f[-1] # 返回最大子數組的和
# 示例
A = [2, 1, -1, 4, 7, 3, 2, 1]
print(maxSubArray(A)) # 輸出應該是 18
這個算法的時間複雜度為O(n)
,空間複雜度也是O(n)
,因為我們使用了n
個額外的存儲空間來存儲f
數組。
最大非降子數組問題(Maximum Non-decreasing Subarray Problem)可以用類似的動態規劃算法來解決,只是在更新f[i]
的時候需要考慮A[i-1]
是否小於或等於A[i]
。