为什么我的算法试图找到最大的子阵列不起作用?

时间:2016-10-11 23:38:59

标签: python algorithm

我尝试根据“算法导论”(第4章)一书实现这种最大子阵列算法。它可以运行,但结果不正确。我在这里找不到逻辑问题。谢谢。

 def find_max_crossing_subarray(A,low,mid,high):      
    leftSum=float('-inf')
    result=0                   ## left_max_sum of midpoint
    maxLeft=0
    maxRight=0

    for i in range(mid,low,-1):
        result=result+A[i]        
        if result>leftSum:
            leftSum=result
            maxLeft=i

    rightSum=float('-inf')
    result2=0                     ##right_max
    for j in range(mid+1,high,1):
        result2=result2+A[j]
        if result2>rightSum:
            rightSum=result2
            maxRight=j
    Result=result+result2        
    return maxLeft,maxRight,Result


def find_maximum_subarray(A,low,high):
    if low==high:
        return low, high, A[low]
    else:
        mid=(low+high)//2
        leftLow,leftHigh,leftSum=find_maximum_subarray(A,low,mid)
        rightLow,rightHigh,rightSum=find_maximum_subarray(A,mid+1,high)
        crossLow, crossHigh,crossSum=find_max_crossing_subarray(A,low,mid,high)
        if leftSum>=rightSum and leftSum>=crossSum:
            return leftLow,leftHigh,leftSum
        elif rightSum>=leftSum and rightSum>=crossSum:
            return rightLow, rightHigh, rightSum
        else:
            return crossLow,crossHigh,crossSum

A=[1,2,30,21]
print (find_maximum_subarray(A,0,len(A)-1))

3 个答案:

答案 0 :(得分:2)

发现它!

find_max_crossing_subarray,而不是range(mid,low,-1)使用range(mid,low-1,-1)而不是range(mid+1,high,1)使用range(mid+1,high+1,1)

进一步解释:

来自range documentation

  

如果step为正,则最后一个元素是最大的start + i *步   少于停止;如果step为负数,则最后一个元素是最小的   开始+ i *步大于停止。

例如,range(0, 5)表示[0, 1, 2, 3, 4]

另请参阅Ryan对Result值的修正。

答案 1 :(得分:0)

当低和中等相同时,for循环不起作用。使用while而不是for是更好的选择。原始版本中的结果也不正确。

def find_max_crossing_subarray(A,low,mid,high):
    leftSum=float('-inf')
    result=0                   ## left_max_sum of midpoint
    maxLeft=0
    maxRight=0
    i=mid
    while i>=low:
        result+=A[i]
        if result>leftSum:
            leftSum=result
            maxLeft=i
        i-=1


    rightSum=float('-inf')
    result2=0 
    j=mid+1                    ##right_max
    while j<=high:
        result2+=A[j]
        if result2>rightSum:
            rightSum=result2
            maxRight=j
        j+=1
    Result=leftSum+rightSum       
    return maxLeft,maxRight,Result

答案 2 :(得分:0)

  

Kadane的算法包括扫描数组值,在每个位置计算在该位置结束的最大(正和)子阵列。此子阵列为空(在这种情况下,其总和为零)或由比在前一位置结束的最大子阵列多一个元素组成。算法只需要跟踪结束位置,因为隐含的起始位置恰好在最后一个位置之后,总和为负;通过删除任何负和前缀,总能找到更高的总和。

本质上,最简单的算法描述了一种解决方案,在该解决方案中,您必须循环遍历数组并找到当前值之前可能存在的最大子数组。

为简化该算法,您可以消除任何负数,并将您的起始索引保留在前一个总和为正的位置。您可以这样做,因为任何数组的空数组的最小总和为

因此,您可以简化算法:

  def mssl(l):
    best = cur = 0
    for i in l:
        cur = max(cur + i, 0)
        best = max(best, cur)
    return best

致谢Wikipedia进行解释。

发现here的同类问题,用户nneonneo给出了很好的答案