《算法导论》4.1-4,4.1-5

这道题在之前基础上,要求在最后判断是否结果小于0,如果最终返回结果小于0,则返回[],直接暴力求解只需要最后返回时进行判断输出即可,但是递归求解时无法在函数中进行判断,所以我在函数外层又加了一层函数。。。。orz

def find_max_cross_subarray(list, low, high, mid):
    """找出跨越中点的最大子数组"""
    left_sum = float("-inf")
    sum = 0
    for i in range(mid, low - 1, -1):
        sum = sum + list[i]
        if sum > left_sum:
            left_sum = sum
            max_left = i
    right_sum = float("-inf")
    sum = 0
    for j in range(mid + 1, high + 1):
        sum = sum + list[j]
        if sum > right_sum:
            right_sum = sum
            max_right = j

    return max_left, max_right, left_sum + right_sum

def find_max_subarray_with_null(list):
    # 增加一层在递归结束后进行判断
    def find_max_subarray(list, low, high):
        # end of induction
        if low == high:
            return low, high, list[low]
        mid = (low + high)/2
        left_low, left_high, left_sum = find_max_subarray(list, low, mid)
        cross_low, cross_high, cross_sum = find_max_cross_subarray(list, low, high, mid)
        right_low, right_high, right_sum = find_max_subarray(list, mid + 1, 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

    max_left, max_right, max_sum = find_max_subarray(list, 0 , len(list)-1)
    if max_sum >= 0:
        return max_left, max_right, max_sum
    else:
        return []

def find_max_subarray_2(list):
    max_sum = float("-inf")
    for i in range(len(list) - 1):
        list_sum = 0
        for j in range(i, len(list) - 1):
            list_sum += list[j]
            if max_sum <= list_sum:
                max_sum = list_sum
                max_left = i
                max_right = j
    if max_sum >= 0:
        return max_left, max_right, max_sum
    else:
        return []


if __name__ == "__main__":
    list = [-13, -3, -25, 20, -3, -16, -23, -18, -20, -7, -3, -5, -22, -15, -5, -7]
    print find_max_subarray_with_null(list)
    print "-" * 50
    print find_max_subarray_2(list)

4.1-5是使用非递归和线性的方法,从数组最左边开始,每次扩展一个数,例如原有A[i:j],扩展一个数时,A[i:j+1],判断A[i:j]原有最大字数组与某新字数组A[k,j+1]的大小取最大的那个,代码如下:

def find_max_subarray_linear(list):
    max_sum = list[0]
    low, high = 0, 0
    for i in range(1, len(list)):
        sum_sub = 0
        for j in range(i, -1, -1):
            sum_sub += list[j]
            if sum_sub >= max_sum:
                max_sum = sum_sub
                low = j
                high = i
    return low, high, max_sum

     ps:最近在学《算法导论》,但是我算法概念很弱,编程基础很差,所以如果看到了错误或者有可以优化的地方,请留言哦~一起进步一起学习!!

点赞