分解(Divide)步骤:将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小
解决(Conquer)步骤:递归地求解出子问题。如果子问题的规模足够小,则停止递归,直接求解
合并(Combine)步骤:将子问题的解组合成原问题的解
有这么一个数组:
[13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
数组中要包含负数, 要不没有意义. 全是正数的数组求和即可.
求出数组中连续和最大的子数组,称为最大子数组.
要找子数组A[low…high]的最大子数组,使用分治法意味着第一步要将数组划分为两个规模尽可能相等的子数组。即找到数组的中央位置,比如mid,第二步求解两个子数组A[low…mid]和A[mid + 1…high]。所以,A[low…high]的任何连续子数组A[i…j]所处的位置必然是三种情况之一:
1.完全位于子数组A[low…mid]中, 因此low≤ i ≤j ≤ mid;
2.完全位于子数组A[mid + 1…high]中,因此mid<=i<=j<=high;
3.跨越了中点,因此low<=i<=mid 还有一种是动态规划的方法求解最大子数组问题,时间可以控制在线性时间.咱们聊到动态规划的时候再说.知道了原理下面看代码Python版本
# coding=utf-8
def Find_Max_SubArray(A, low, high):
"""
找到最大子数组
"""
if high == low:
# 这里是递归返回, 一步一步递归最后只剩一个就是最大的
return [low, high, A[low - 1]]
else:
mid = (low + high) // 2
left = Find_Max_SubArray(A, low, mid)
right = Find_Max_SubArray(A, mid+1, high)
cross = Find_Max_Cross_SubArray(A, low, mid, high)
if left[2] >= right[2] and left[2] >= cross[2]:
return left
elif right[2] >= left[2] and right[2] >= cross[2]:
return right
else:
return cross
def Find_Max_Cross_SubArray(A, low, mid, high):
"""
最大子数组范围在low<=i<=mid<=j<=high
"""
left_sum = float('-inf')
sum = 0
max_left = 0
for i in range(mid, low, -1):
sum = sum + int(A[i])
if sum > left_sum:
left_sum = sum
max_left = i
right_sum = float('-inf')
sum = 0
max_right = 0
for j in range(mid + 1, high):
sum = sum + A[j]
if sum > right_sum:
right_sum = sum
max_right = j
return [max_left, max_right, (left_sum + right_sum)]
if __name__ == '__main__':
import random
randomlist = random.sample(range(-20, 20), 16)
low = 0
high = len(randomlist)
print("数组为: ", randomlist)
print("最大子数组为: ", Find_Max_SubArray(randomlist, low, high))
C语言版本:
#include