3

我正在尝试实现一种方法来获取 maxSubArray 总和以及相关的开始和结束索引。作为参考,maxSubArray 是连续子数组,其整数和是所有子数组中最大的。我的总和正确,结束索引正确,但我在开始时遇到了麻烦。我已经解释了一件小事,但无论我做什么,我似乎都无法解释所有的情况。每当我解释一个时,另一个就会出现。显然,在线性时间内得到总和是可能的,但我似乎无法找到一种有效地获得正确起始索引的方法。

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
4

2 回答 2

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_

编辑:请注意,此处的结束索引是独占的。

此外,如果有多个最优子数组,则返回第一个也是最长的。

于 2013-10-30T04:25:36.357 回答
1

这个问题对我来说似乎很熟悉......快速搜索出现了维基百科文章最大子数组问题。改编自那篇文章中的 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
于 2013-10-30T05:22:46.607 回答