Python中max子数组的索引不正确

时间:2015-01-28 01:46:09

标签: python algorithm

我在Python中编写了一个蛮力和分而治之的Max Subarray问题实现。通过绘制随机的整数样本来运行测试。

当输入数组的长度很大时, __main__中的断言失败,因为递归算法没有返回正确的答案。但是,当阵列长度小于10个元素时,这两个算法会同意(这是近似值,并且每次执行时失败输入的实际大小会有所不同)。该问题似乎与偶数或奇数数组长度无关,但它似乎与数组索引的方式有关。

很抱歉,如果我错过了一些愚蠢的东西,但为什么递归算法会在输入数组开始变大时停止返回正确的输出?

# Subarray solutions are represented by an array in the form
# [lower_bound, higher_bound, sum]

from sys import maxsize
import random
import time

# Brute force implementation (THETA(n^2))
def bf_max_subarray(A):
    biggest = -maxsize - 1

    left = 0
    right = 0

    for i in range(0, len(A)):
        sum = 0
        for j in range(i, len(A)):
            sum += A[j]
            if sum > biggest:
                biggest = sum
                left = i
                right = j   

    return [left, right, biggest]

# Part of divide-and-conquer solution   
def cross_subarray(A, l, m, r): 
    lsum   = -maxsize - 1
    rsum   = -maxsize - 1
    lbound = 0
    rbound = 0

    tempsum = 0
    for i in range(m, l-1, -1):
        tempsum += A[i]
        if tempsum > lsum:
            lsum = tempsum
            lbound = i

    tempsum = 0
    for j in range(m+1, r+1):
        tempsum += A[j]
        if tempsum > rsum:
            rsum = tempsum
            rbound = j

    return [lbound, rbound, lsum + rsum]

# Recursive solution
def rec_max_subarray(A, l, r):
    # Base case: array of one element
    if (l == r):
        return [l, r, A[l]]
    else:
        m = (l+r)//2

        left  = rec_max_subarray(A, l, m)
        right = rec_max_subarray(A, m+1, r)
        cross = cross_subarray(A, l, m, r)

        # Returns the array representing the subarray with the maximum sum.
        return max([left, right, cross], key=lambda i:i[2])

if __name__ == "__main__":
    for i in range(1, 101):
        A = random.sample(range(-i*2, i), i)

        start = time.clock()
        bf = bf_max_subarray(A)
        bf_time = time.clock() - start

        start = time.clock()
        dc = rec_max_subarray(A, 0, len(A)-1)
        dc_time = time.clock() - start

        assert dc == bf # Make sure the algorithms agree.

1 个答案:

答案 0 :(得分:0)

具有最大总和的子数组由[left_bound, right_bound, sum]形式的数组表示。

但是由于return max([left, right, cross], key=lambda i:i[2])rec_max_subarray会返回A的正确最大总和,但有可能返回与bf_max_subarray中返回的指标不匹配的指标。 我的错误是假设具有最大总和的子阵列的边界将是唯一的。

解决方案是修复选择子数组的条件,或者只是使用assert dc[2] == bf[2]来断言总和的相等性。