最大子數列

最大子數列問題(Maximum Subarray Problem)是一個經典的動態規劃問題,其目標是在一個整數數列中找到一段連續的子數列,使得這段子數列的和最大。

例如,給定數列 [-2, 11, -4, 13, -5, -2],其中最大的子數列和為 21,這段子數列是 [11, -4, 13]

解決這個問題的動態規劃算法如下:

  1. 定義狀態:我們可以使用一個二維數組 dp 來記錄每一個數列元素的子數列的最大和。dp[i][j] 表示數列 A[i..j] 的最大子數列和。

  2. 狀態轉移方程:對於每個 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],因為加上一個負數只會讓和變小。
  3. 初始條件: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。這是一個貪心算法,它通過維護一個累加和以及一個最大累加和來找到最大子數列和。這裡就不詳細介紹了,有興趣的可以自行查找相關資料。