最大子数组问题
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
使用分治法,A[low…high]的任意连续子数组A[i…j]所处的位置必然是以下三种情况之一:
(a)完全位于子数组A[low…mid]中,因此low≤i≤j≤mid
(b)完全位于子数组A[mid+1…high]中,因此mid≤i≤j≤high
(c)跨越了中点,因此low≤i≤mid≤j≤high
分别找它们中的最大子数组就好了
# 找跨过中点的
def cross(A, low, mid, high):
left_sum = -65536
sum = 0
max_left = max_right = 0
# 找左边的最大数组
i = mid
while i >= low:
sum += A[i]
if sum > left_sum:
left_sum = sum
max_left = i
i-=1
right_sum = -65536
sum = 0 # sum重新置为0
# 找右边的最大数组
j = mid+1
while j <= high:
sum += A[j]
if sum > right_sum:
right_sum = sum
max_right = j
j+=1
return max_left,max_right,(left_sum+right_sum)
# 找子数组,返回值为改子数组的 最小索引,最大索引,和
def find_ma(A, low, high):
if low == high:
return low, high, A[low]
mid = int((low+high)/2)
left_low, left_high, left_sum = find_ma(A, low, mid)
right_low, right_high, right_sum = find_ma(A, mid+1, high)
cross_low, cross_high, cross_sum = cross(A, low, mid, high)
if left_sum > right_sum and left_sum > cross_sum:
return left_low, left_high, left_sum
elif left_sum < cross_sum and right_sum < cross_sum:
return cross_low, cross_high, cross_sum
else:
return right_low, right_high, right_sum
# 测试
arr = [1,-1,2,3,-5,1,-4]
a,b,c = find_ma(arr,0,6)
print(a,b,c)
2 3 5