最大子數列
最大子數列問題(Maximum Subarray Problem)是一個經典的動態規劃問題,其目標是在一個整數數列中找到一段連續的子數列,使得這段子數列的和最大。
例如,給定數列 [-2, 11, -4, 13, -5, -2]
,其中最大的子數列和為 21
,這段子數列是 [11, -4, 13]
。
解決這個問題的動態規劃算法如下:
-
定義狀態:我們可以使用一個二維數組
dp
來記錄每一個數列元素的子數列的最大和。dp[i][j]
表示數列A[i..j]
的最大子數列和。 -
狀態轉移方程:對於每個
i
,我們需要考慮兩種情況來更新dp[i][i]
:- 如果
A[i]
加上dp[i-1][i-1]
(前一個子數列的最大和)是正數,那麼dp[i][i]
應該被更新為這兩個數的和。 - 如果
A[i]
加上dp[i-1][i-1]
是負數,那麼dp[i][i]
應該保持為dp[i-1][i-1]
,因為加上一個負數只會讓和變小。
- 如果
-
初始條件:
dp[0][0]
表示數列A[0..0]
的最大子數列和,這應該是A[0]
本身。
以下是一個可能的實現:
def maxSubArray(A):
n = len(A)
dp = [[0] * n for _ in range(n)]
# 初始化第一行和第一列
for i in range(n):
dp[0][i] = A[i]
dp[i][0] = A[i]
# 填入 dp 數組
for i in range(1, n):
for j in range(1, n):
dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + A[j]
# 返回最大子數列和
return max(dp[-1][-1])
這個算法的時間複雜度為 O(n^2)
,空間複雜度為 O(n^2)
,因為我們使用了一個二維數組 dp
。
對於這個問題,還有另一種時間複雜度為 O(n)
的算法,稱為Kadane's algorithm。這是一個貪心算法,它通過維護一個累加和以及一個最大累加和來找到最大子數列和。這裡就不詳細介紹了,有興趣的可以自行查找相關資料。