【Python】給定一個數組A[0,…,n-1],求A的連續子陣列,使得該子陣列的和最大
阿新 • • 發佈:2019-01-29
最大子陣列
給定一個數組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