我在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.
答案 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]
来断言总和的相等性。