1 # 先求解第三种跨越中点的情况 2 def find_max_crossing_subarry(A, low, mid, high): 3 # 求解最大的A[L, mid](mid 始终不变, L >= i) 4 left_sum = -float('inf') 5 suml = 0 6 max_left = mid 7 for i in range(mid): 8 suml = suml + A[mid-i] 9 if suml > left_sum: 10 left_sum = suml 11 max_left = mid - i 12 13 #求最大的A[mid, R](mid 始终不变, j >= R >= mid) 组成 14 right_sum = -float('inf') 15 sumr = 0 16 max_right = mid 17 for j in range(mid+1,high-1): 18 sumr = sumr + A[j] 19 if sumr > right_sum: 20 right_sum = sumr 21 max_right = j 22 23 return max_left, max_right, left_sum + right_sum 24 25 # 递归求解 a,b 两种情况的的 最大子数组的 candidate, 通过跟请况 c 的最大子数组 candidate 对比, return 最大子数组. 26 def find_max_subarry(A, low, high): 27 if high == low: 28 return low, high, A[low] 29 else: 30 mid = ((low + high) // 2) 31 32 # 递归求解情况 a 33 left_low, left_high, left_sum = find_max_subarry(A, low, mid) 34 35 # 递归求解情况 b 36 right_low, right_high, right_sum = find_max_subarry(A, mid+1, high) 37 # 求解情况 c (跨中点的情况) 38 cross_low, cross_high, cross_sum = find_max_crossing_subarry(A, low, mid, high) 39 40 # 通过对比 3 种情况中最大子数组的 candidate, 返回 candidate 中的'最大者' 即为所求的 '最大子数组'. 41 print('Candiate A :', A[left_low: left_high] ) 42 print('Candiate B :', A[right_low: right_high]) 43 print('Candiate C :', A[cross_low: cross_high]) 44 if left_sum >= right_sum and left_sum >= cross_sum: 45 return left_low, left_high, left_sum 46 elif right_sum >= left_sum and right_sum >= cross_sum: 47 return right_low, right_high, right_sum 48 else: 49 return cross_low, cross_high, cross_sum 50 51 52 if __name__ == '__main__': 53 54 A = [13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7] 55 56 a,b,c = find_max_subarry(A, 0, 15) 57 58 print('The maximum subarry is ', A[a:b+1]) 59 print('The aximum profit is %d . Buy in on day %d, and sale out on day %d .'% (c, a+1, b+1 ))
结果打印
1 Candiate A : [] # 情况 a 的 最大子数组 candidate 2 Candiate C : [20] 3 Candiate C : [20, -3, -16] 4 Candiate C : [20, -3] 5 Candiate C : [20] 6 Candiate C : [18] 7 Candiate C : [18, 20, -7] 8 Candiate C : [18, 20] 9 Candiate C : [18, 20, -7, 12, -5] 10 Candiate C : [18, 20, -7, 12, -5, -22, 15] # 情况 c 的 最大子数组 candidate 11 Candiate C : [18, 20, -7, 12, -5, -22] 12 Candiate C : [18, 20, -7, 12, -5, -22] 13 Candiate B : [18, 20, -7, 12, -5, -22] # 情况 b 的 最大子数组 candidate 14 Candiate C : [18, 20, -7] 15 16 # 结果 17 The maximum subarry is [18, 20, -7, 12] 18 The aximum profit is 43 . Buy in on day 8, and sale out on day 11 .
Reference
1,Introduction to algorithms