最大子数组问题

来源:互联网 发布:中建上海设计院 知乎 编辑:程序博客网 时间:2024/05/22 03:13

最大子数组问题

问题描述

Find the contiguous subarray within an array (containing at least one number) which has the largest sum. 
For example, given the array [−2,1,−3,4,−1,2,1,−5,4], 
the contiguous subarray [4,−1,2,1] has the largest sum = 6.

暴力求解法:

# -*- coding:utf-8 -*-def max_subarray(source):    sum_max = -float("inf")    array_max = []    for i in range(len(source)):        for j in range(i+1, len(source)):           sum_now = sum(list[i:j+1])           if sum_now > sum_max:               sum_max = sum_now               array_max = list[i:j+1]    return array_maxprint max_subarray([13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7])

分治法:

其实就是分解成最小的子问题,求解跨越数组中点的最大子数组问题

伪代码,摘抄自算法导论P42

FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)left_sum = - Infsum = 0for i = mid downto lowsum = sum + a[i]if sum > left_sumleft_sum = summax_left = iright_sum = - Infsum = 0for j = mid + 1 to highsum = sum + a[i]if sum > right_sumright_sum = summax_right = jreturn (max_left, max_right, left_sum + right_sum)FIND-MAX-SUBARRAY(A,low,high)if high == low:return (low, high, A[low])elsemid = [(low + high) / 2]//[]是取整(left_low,left_high,left_sum) = FIND-MAX-SUBARRAY(A,low,mid)(right_low,right_high,right_sum) = FIND-MAX-SUBARRAY(A,mid+1,high)(cross_low,cross_high,cross_sum) = FIND-MAX-CROSSING-SUBARRAY(A,low,mid,high)if left_sum >= right_sum and left_sum >= cross_highreturn (left_low, left_high, left_sum)else if right_sum >= left_sum and right_sum >= cross_sumreturn (right_low, right_high, right_sum)elsereturn (cross_low, cross_high, cross_sum)


使用python的实现:

def max_crossing_subarray(source, low, mid, high):    left_sum = float("-Inf")    right_sum = float("-Inf")    #   累加值初始化为正无穷    sum_now = 0    for i in range(mid, low-1, -1):        sum_now = sum(source[mid: i-1: -1])        if sum_now > left_sum:            left_sum = sum_now            max_left = i    sum_now = 0    for j in range(mid+1, high+1):        sum_now = sum(source[mid+1:j+1])        if sum_now > right_sum:            right_sum = sum_now            max_right = j    #   找到从mid起始分别到左边和右边的最大子数组    return max_left, max_right, left_sum + right_sum#   将左边的最大子数组与右边的最大子数组合并def max_array(source, low, high):    if high == low:        return low, high, source[low]    else:        mid = (low+high)/2        left_low, left_high, left_sum = max_array(source, low, mid)        #   左边的最大子数组        right_low, right_high, right_sum = max_array(source, mid+1, high)        #   右边的最大子数组        cross_low, cross_high, cross_sum = max_crossing_subarray(source, low, mid, high)        #   跨越中点的最大子数组        if left_sum >= right_sum and left_sum >= cross_sum:            return left_low, left_high, left_sum        elif right_sum >= left_sum and right_sum >= cross_sum:            return right_low, right_high, right_sum        else:            return cross_low, cross_high, cross_sum        #   三种情况互相比较,返回最大的情况a = [14, -2, -17, 2, 8, 9, -20, 11]print max_array(a, 0, 7)




原创粉丝点击