我正在尝试实现一个方法来获取maxSubArray和以及相关的开始和结束索引。作为参考,maxSubArray是连续的subArray,其整数和是所有subArrays中最大的。我总和正确,结束索引正确,但我开始时遇到了麻烦。我已经解决了一个微不足道的案例,但无论我做什么,我似乎无法解释所有案件。每当我占一个,另一个出现。显然,在线性时间内得到总和是可能的,但我似乎无法找到一种方法来有效地获得正确的起始指数。
def maxSubArray(seq):
#max_i = max ending at i, max_gen = best max up until i
max_i = max_gen = beg = end = prev_max = 0
for i in xrange(len(seq)):
#use dynamic programming to get maxSubArray sum (works)
max_i = max(0, max_i + seq[i])
max_gen = max(max_gen, max_i)
#get correct end (works)
if prev_max < max_gen:
end = i
prev_max = max_gen
if max_gen == 0:
max_gen = max(seq)
beg = end = seq.index(max_gen)
return [max_gen, beg, end]
就像我说的那样,我尝试了很多东西,但是随着每一种新方式引入新旧问题,我们继续删除它们。有人有任何建议/解决方案吗?我在Java标签下看到了类似的问题,但答案不正确。为方便起见,我提供了一种我知道可行的蛮力方法,以及我一直使用的迷你测试仪:
def bruteForceCheck(seq):
maxV = [float('-inf'), 0, 0]
for i in xrange(len(seq)):
for j in xrange(i,len(seq)):
if (sum(seq[i:j+1]) > maxV[0]):
maxV = [sum(seq[i:j+1]), i, j]
return maxV
if __name__ == "__main__":
for i in xrange(1000):
l = []
for j in xrange(15):
num = random.randint(-1000,1000)
#didn't feel like dealing with issue of two methods
#choosing to count or not count 0s
while (num == 0):
num = random.randint(-1000,1000)
l.append(num)
msa = maxSubArray(l)
bfc = bruteForceCheck(l)
if msa != bfc:
print l
print msa
print bfc
break
答案 0 :(得分:2)
请原谅我,但这很有效,而且是Pythonic。
def maxSubArray(seq):
all_sum = cur_sum = 0
all_beg = cur_beg = 0
all_end = 0
for cur_end, x in enumerate(seq, 1):
if cur_sum + x > 0:
cur_sum += x
if all_sum < cur_sum:
all_sum = cur_sum
all_beg, all_end = cur_beg, cur_end
else:
cur_sum = 0
cur_beg = cur_end
return all_sum, all_beg, all_end
算法是一样的。对于此处结束的数组(cur_
)和整体(all_
),有sum,起始索引和结束索引。
编辑:请注意,此处的结束索引是独占的。
此外,如果有多个最佳子阵列,则返回第一个和最长的子阵列。
答案 1 :(得分:1)
这个问题对我来说似乎很熟悉......快速搜索出现了维基百科文章Maximum subarray problem。改编自该文章中的c ++解决方案
def maxSubArray(seq):
max_so_far = seq[0]
max_ending_here = 0
begin = 0
begin_temp = 0
end = 0
for i in xrange(1, len(seq)):
if max_ending_here < 0:
max_ending_here = seq[i]
begin_temp = i
else:
max_ending_here += seq[i]
if max_ending_here >= max_so_far:
max_so_far = max_ending_here
begin = begin_temp
end = i
return max_so_far, begin, end