1

我尝试将 CLRS 算法简介中给出的最大子数组问题的伪代码转换为 Python 中的完整工作代码。

代码:

def cross(A,low,mid,high):
    left_sum = -float("inf")
    s = 0
    i = mid

    while (i >= low):
        s = s + A[i]
        if s > left_sum:
            left_sum = s
            max_left = i
        i = i - 1

    right_sum = -float("inf")
    s = 0
    j = mid + 1

    while (j < high):
        s = s + A[j]
        if s > right_sum:
            right_sum = s
            max_right = j
        j = j + 1

    return (max_left,max_right,left_sum+right_sum)

def maxSubarray(A,low,high):
    if high == low: return (low,high,A[low])
    else:
        mid = (low+high)/2
        (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
        (right_low,right_high,right_sum) = maxSubarray(A,mid+1,high)
        (cross_low,cross_high,cross_sum) = cross(A,low,mid,high)

        if (left_sum >= right_sum & left_sum >= cross_sum):return (left_low,left_high,left_sum)
        elif (right_sum >= left_sum & right_sum >= cross_sum):return (right_low,right_high,right_sum)
        else: return (cross_low,cross_high,cross_sum)
t = [13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7]

print maxSubarray(t,0,16)

当我尝试运行时,我收到此错误。

错误:

Traceback (most recent call last):
  File "/home/suyash/Downloads/python/max_subarray.py", line 64, in <module>
    print maxSubarray(t,0,16)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 53, in maxSubarray
    (cross_low,cross_high,cross_sum) = cross(A,low,mid,high)
  File "/home/suyash/Downloads/python/max_subarray.py", line 39, in cross
    return (max_left,max_right,left_sum+right_sum)
UnboundLocalError: local variable 'max_right' referenced before assignment

我怎样才能解决这个问题?我哪里出错了?

4

3 回答 3

1

两个非常小的错误:

  1. 您的列表t长度为 16。这意味着最后一个索引是 15。因此maxSubarray(t,0,15)不调用maxSubarray(t,0,16)
  2. while (j <= high). 循环直到j<= high直到j<high

同样通过这两个修复,您无需将任何默认值设置为max_rightor max_right。在每个递归调用中,while任何if条件都将始终为 True。

演示:

>>> def cross(A,low,mid,high):
...     left_sum = -float("inf")
...     s = 0
...     i = mid
...     while (i >= low):
...         s = s + A[i]
...         if s > left_sum:
...             left_sum = s
...             max_left = i
...         i = i - 1
...     right_sum = -float("inf")
...     s = 0
...     j = mid + 1
...     while (j <= high):  # Loop until j<= high not until j<high
...         s = s + A[j]
...         if s > right_sum:
...             right_sum = s
...             max_right = j
...         j = j + 1
...     return (max_left,max_right,left_sum+right_sum)
... 
>>> def maxSubarray(A,low,high):
...     if high == low: return (low,high,A[low])
...     else:
...         mid = (low+high)/2
...         (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
...         (right_low,right_high,right_sum) = maxSubarray(A,mid+1,high)
...         (cross_low,cross_high,cross_sum) = cross(A,low,mid,high)
...         if (left_sum >= right_sum & left_sum >= cross_sum):return (left_low,left_high,left_sum)
...         elif (right_sum >= left_sum & right_sum >= cross_sum):return (right_low,right_high,right_sum)
...         else: return (cross_low,cross_high,cross_sum)
... 
>>> t = [13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7]
>>> print maxSubarray(t,0,15)  # Last index = 15 not 16
(7, 10, 43)  # This shows max subarray is from index 7 to 10 i.e., [18,20,-7,12] and the sum is 43
于 2014-12-15T09:26:14.330 回答
0

你忘了考虑边界条件。

当一个通常成功的条件突然失败时,可能会出现这样的情况,从而使变量未绑定。无论如何,您都需要确保该变量具有合理的默认值。

于 2014-12-15T09:02:15.377 回答
0

max_right您只能在循环内的if语句中进行分配while,这意味着如果您遇到异常,则要么s > right_sum永远不会j < high为真:

while (j < high):
    s = s + A[j]
    if s > right_sum:
        right_sum = s
        max_right = j
    j = j + 1

您应该在该循环之外max_right给出一个默认值;在这里是合适的。whilemax_right = high

于 2014-12-15T09:02:34.423 回答