最大子數組問題

最大子數組問題

問題描述

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_max

print 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 = - Inf
	sum = 0
	for i = mid downto low
		sum = sum + a[i]
		if sum > left_sum
			left_sum = sum
			max_left = i
			
	right_sum = - Inf
	sum = 0
	for j = mid + 1 to high
		sum = sum + a[i]
		if sum > right_sum
			right_sum = sum
			max_right = j
			
	return (max_left, max_right, left_sum + right_sum)

FIND-MAX-SUBARRAY(A,low,high)
	if high == low:
		return (low, high, A[low])
	else
		mid = [(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_high
			return (left_low, left_high, left_sum)
		else if right_sum >= left_sum and right_sum >= cross_sum
			return (right_low, right_high, right_sum)
		else
			return (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)




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章