1. 程式人生 > >【Python】給定一個數組A[0,…,n-1],求A的連續子陣列,使得該子陣列的和最大

【Python】給定一個數組A[0,…,n-1],求A的連續子陣列,使得該子陣列的和最大

最大子陣列

給定一個數組A[0,…,n-1],求A的連續子陣列,使得該子陣列的和最大。
例如陣列: 1, -2, 3, 10, -4, 7, 2, -5
最大子陣列:3, 10, -4, 7, 2

演算法分析

定義:字首和sum[i] = a[0] + a[1] + …+a[i]
則:a[i,j]=sum[j]-sum[i-1](定義sum[-1] = 0)
演算法過程
1. 求i字首sum[i]:
遍歷i:0≤i≤n-1
sum[i]=sum[i-1]+a[i]
2. 計算以a[i]結尾的子陣列的最大值對於某個i:遍歷0≤j≤i,求sum[j]的最小值m
sum[i]-m即為以a[i]結尾的陣列中最大的子陣列的值
3. 統計sum[i]-m的最大值, 0≤i≤n-1
1、2、3步都是線性的,因此,時間複雜度O(n)。

進一步的分析

記S[i]為以A[i]結尾的陣列中和最大的子陣列
則:S[i+1] = max(S[i]+A[i+1], A[i+1])
S[0]=A[0]
遍歷i: 0≤i≤n-1
動態規劃:最優子問題
時間複雜度:O(n)

Python程式碼

# 輸出最大子陣列的和
def max_subarray(li):
    if li is None or len(li) == 0:
        return 0
    s = li[0]  # 當前子串的和
    result = s  # 當前找到的最優解
    for i in range(len(li)):
        if
s > 0: s += li[i] else: s = li[i] result = max(s, result) return result # 除了輸出最大子陣列的和,還需要輸出最大子陣列本身 def max_subarray2(li): if li is None or len(li) == 0: return 0 s = li[0] # 當前子串的和 result = s # 當前找到的最優解 fromIndex = toIndex = 0 # from=to=0
fromIndexNew = 0 # 新的子陣列起點 for i in range(len(li)): if s > 0: s += li[i] else: s = li[i] fromIndexNew = i if result < s: result = s fromIndex = fromIndexNew toIndex = i print(li[fromIndex:toIndex + 1]) return result if __name__ == '__main__': li = [1, -2, 3, 10, -4, 7, 2, -5] result = max_subarray2(li) print(result)

輸出結果:
[3, 10, -4, 7, 2]
18