Python θ(n**2)和θ(n*lgn)算法执行不正确

Python θ(n**2)和θ(n*lgn)算法执行不正确,python,algorithm,python-2.7,Python,Algorithm,Python 2.7,我正在读算法简介,并试图完成书中的练习 在练习4.1-3中 4.1-3 在您自己的计算机上实现最大子阵列问题的蛮力算法和递归算法。n0给出的交叉问题大小是多少 递归算法打败蛮力算法的点?那么, 将递归算法的基本情况更改为使用蛮力算法 当问题大小小于n0时。这会改变交叉点吗 我根据书中的伪代码编写了这两个算法。但是,我的代码一定有问题,因为第二个代码被设计为θ(n*lgn)并且应该运行得更快,它总是比第一个θ(n**2)代码运行得慢。我的代码如下所示 def find_maximum_subarr

我正在读算法简介,并试图完成书中的练习

在练习4.1-3中

4.1-3 在您自己的计算机上实现最大子阵列问题的蛮力算法和递归算法。n0给出的交叉问题大小是多少 递归算法打败蛮力算法的点?那么, 将递归算法的基本情况更改为使用蛮力算法 当问题大小小于n0时。这会改变交叉点吗

我根据书中的伪代码编写了这两个算法。但是,我的代码一定有问题,因为第二个代码被设计为θ(n*lgn)并且应该运行得更快,它总是比第一个θ(n**2)代码运行得慢。我的代码如下所示

def find_maximum_subarray_bf(a): #bf for brute force p1 = 0 l = 0 # l for left r = 0 # r for right max_sum = 0 for p1 in range(len(a)-1): sub_sum = 0 for p2 in range(p1, len(a)): sub_sum += a[p2] if sub_sum > max_sum: max_sum = sub_sum l = p1 r = p2 return l, r, max_sum def find_maximum_subarray_dc(a): #dc for divide and conquer # subfunction # given an arrary and three indics which can split the array into a[l:m] # and a[m+1:r], find out a subarray a[i:j] where l \leq i \less m \less j \leq r". # according to the definition above, the target subarray must # be combined by two subarray, a[i:m] and a[m+1:j] # Growing Rate: theta(n) def find_crossing_max(a, l, r, m): # left side # ls_r and ls_l indicate the right and left bound of the left subarray. # l_max_sum indicates the max sum of the left subarray # sub_sum indicates the sum of the current computing subarray ls_l = 0 ls_r = m-1 l_max_sum = None sub_sum = 0 for j in range(m+1)[::-1]: # adding elements from right to left sub_sum += a[j] if sub_sum > l_max_sum: l_max_sum = sub_sum ls_l = j # right side # rs_r and rs_l indicate the right and left bound of the left subarray. # r_max_sum indicates the max sum of the left subarray # sub_sum indicates the sum of the current computing subarray rs_l = m+1 rs_r = 0 r_max_sum = None sub_sum = 0 for j in range(m+1,len(a)): sub_sum += a[j] if sub_sum > r_max_sum: r_max_sum = sub_sum rs_r = j #combine return (ls_l, rs_r, l_max_sum+r_max_sum) # subfunction # Growing Rate: should be theta(nlgn), but there is something wrong def recursion(a,l,r): # T(n) if r == l: return (l,r,a[l]) else: m = (l+r)//2 # theta(1) left = recursion(a,l,m) # T(n/2) right = recursion(a,m+1,r) # T(n/2) crossing = find_crossing_max(a,l,r,m) # theta(n) if left[2]>=right[2] and left[2]>=crossing[2]: return left elif right[2]>=left[2] and right[2]>=crossing[2]: return right else: return crossing #back to master function l = 0 r = len(a)-1 return recursion(a,l,r) if __name__ == "__main__": from time import time a = [100,-10,1,2,-1,4,-6,2,5] a *= 2**10 time0 = time() find_maximum_subarray_bf(a) time1 = time() find_maximum_subarray_dc(a) time2 = time() print "function 1:", time1-time0 print "function 2:", time2-time1 print "ratio:", (time1-time0)/(time2-time1) def find_maximum_subarray_bf(a):#蛮力的bf p1=0 l=0#l表示左侧 r=0#r表示右侧 最大和=0 对于范围内的p1(透镜(a)-1): 次和=0 对于范围内的p2(p1,len(a)): 子总和+=a[p2] 如果子总和>最大总和: 最大和=次和 l=p1 r=p2 返回l,r,最大和 def find_maximum_subarray_dc(a):#用于分治的dc #子功能 #给定一个数组和三个可以将数组拆分为[l:m]的指示符 #和a[m+1:r],找出子阵a[i:j],其中l\leq i\less m\less j\leq r”。 #根据上面的定义,目标子阵列必须 #由两个子阵a[i:m]和a[m+1:j]组合而成 #增长率:θ(n) def find_crossing_max(a、l、r、m): #左侧 #ls_r和ls_l表示左子阵列的右边界和左边界。 #l_max_sum表示左子阵列的最大和 #sub_sum表示当前计算子阵列的和 ls_l=0 ls_r=m-1 l_max_sum=无 次和=0 对于范围(m+1)[::-1]:#从右向左添加元素 子_和+=a[j] 如果sub_sum>l_max_sum: l_max_sum=子_sum ls_l=j #右侧 #rs_r和rs_l表示左子阵列的右边界和左边界。 #r_max_sum表示左子数组的最大和 #sub_sum表示当前计算子阵列的和 rs_l=m+1 rs_r=0 r_max_sum=无 次和=0 对于范围(m+1,len(a))内的j: 子_和+=a[j] 如果sub_sum>r_max_sum: r_max_sum=次和 rs_r=j #结合 返回值(ls\u l、rs\u r、l\u max\u sum+r\u max\u sum) #子功能 #增长率:应该是θ(nlgn),但有点不对劲 def递归(a,l,r):#T(n) 如果r==l: 返回(l,r,a[l]) 其他: m=(l+r)//2#θ(1) 左=递归(a,l,m)#T(n/2) 右=递归(a,m+1,r)#T(n/2) 交叉=找到交叉点最大值(a,l,r,m)#θ(n) 如果左[2]>=右[2]和左[2]>=交叉[2]: 左转 elif right[2]>=左[2]和right[2]>=交叉点[2]: 返回权 其他: 回程交叉口 #返回主控功能 l=0 r=len(a)-1 返回递归(a,l,r) 如果名称=“\uuuuu main\uuuuuuuu”: 从时间导入时间 a=[100,-10,1,2,-1,4,-6,2,5] a*=2**10 time0=时间() 查找\u最大\u子阵列\u bf(a) time1=时间() 查找\u最大\u子阵列\u dc(a) time2=时间() 打印“功能1:”,时间1-0 打印“功能2:”,时间2-1 打印“比率:”,(time1-time0)/(time2-time1)
首先,暴力中的一个错误:

for p1 in range(len(a)-1):
这应该是
range(len(a))
[或
xrange
],也就是说,它找不到
[-12,10]
的最大子数组

现在,递归:

def find_crossing_max(a, l, r, m):

    # left side
    # ls_r and ls_l indicate the right and left bound of the left subarray.
    # l_max_sum indicates the max sum of the left subarray
    # sub_sum indicates the sum of the current computing subarray      
    ls_l = 0
    ls_r = m-1
    l_max_sum = None
    sub_sum = 0
    for j in range(m+1)[::-1]:      # adding elements from right to left
您正在将所有索引检查为0,但只应将索引检查为
l
。使用
xrange(m,l-1,-1)

对于右边的和,模拟值成立,您应该只检查
r
,因此
xrange(m+1,r+1)

此外,最大子数组的和与索引的初始值对于左侧部分是可疑的,对于右侧是错误的

对于左边的部分,我们从一个空和开始,但必须包括
a[m]
。这可以通过设置
l\u max\u sum=None
开始,或者通过设置
l\u max\u sum=a[m]来实现
并让
j
忽略索引
m
。无论哪种方式,
ls\u l
的初始值不应为
0
,而
ls\u r
的初始值不应为
m-1
ls\u r
必须为
m
,如果
ls\u l
的初始值为
m+1
de>为
None
,如果
l\u max\u sum
a[m]
开头,则为
m

对于正确的部分,
r\u max\u sum
必须从0开始,而
r\u r
最好从
m
开始(虽然这并不重要,但它只会给你错误的索引)。如果右边的和都不是非负的,那么正确的和应该是
0
,而不是负和中的最大值

在递归中,我们在

left = recursion(a,l,m)         # T(n/2)
包括
a[m]
在内的总和已经在
find\u crossing\u max
中进行了处理或优化,因此可以

left = recursion(a,l,m-1)
但是,我们还必须在递归中处理可能性
r
,重复性很小,所以我就让这种情况继续下去

因为你总是穿越整个世界
left = recursion(a,l,m-1)
def find_maximum_subarray_bf(a):        #bf for brute force
    p1 = 0
    l = 0           # l for left
    r = 0           # r for right
    max_sum = 0
    for p1 in xrange(len(a)):
        sub_sum = 0
        for p2 in xrange(p1, len(a)):
            sub_sum += a[p2]
            if sub_sum > max_sum:
                max_sum  = sub_sum
                l = p1
                r = p2
    return l, r, max_sum

def find_maximum_subarray_dc(a):        #dc for divide and conquer

    # subfunction
    # given an arrary and three indices which can split the array into a[l:m]
    # and a[m+1:r], find out a subarray a[i:j] where l \leq i \less m \less j \leq r".
    # according to the definition above, the target subarray must
    # be combined by two subarray, a[i:m] and a[m+1:j]
    # Growing Rate: theta(n)

    def find_crossing_max(a, l, r, m):

        # left side
        # ls_r and ls_l indicate the right and left bound of the left subarray.
        # l_max_sum indicates the max sum of the left subarray
        # sub_sum indicates the sum of the current computing subarray      
        ls_l = m+1
        ls_r = m
        l_max_sum = None
        sub_sum = 0
        for j in xrange(m,l-1,-1):      # adding elements from right to left
            sub_sum += a[j]
            if sub_sum > l_max_sum:
                l_max_sum = sub_sum
                ls_l = j

        # right side
        # rs_r and rs_l indicate the right and left bound of the left subarray.
        # r_max_sum indicates the max sum of the left subarray
        # sub_sum indicates the sum of the current computing subarray                
        rs_l = m+1
        rs_r = m
        r_max_sum = 0
        sub_sum = 0
        for j in range(m+1,r+1):
            sub_sum += a[j]
            if sub_sum > r_max_sum:
                r_max_sum = sub_sum
                rs_r = j

        #combine
        return (ls_l, rs_r, l_max_sum+r_max_sum)

    # subfunction
    # Growing Rate:  theta(nlgn)
    def recursion(a,l,r):           # T(n)
        if r == l:
            return (l,r,a[l])
        else:
            m = (l+r)//2                    # theta(1)
            left = recursion(a,l,m)         # T(n/2)
            right = recursion(a,m+1,r)      # T(n/2)
            crossing = find_crossing_max(a,l,r,m)   # theta(r-l+1)

            if left[2]>=right[2] and left[2]>=crossing[2]:
                return left
            elif right[2]>=left[2] and right[2]>=crossing[2]:
                return right
            else:
                return crossing

    #back to master function
    l = 0
    r = len(a)-1
    return recursion(a,l,r)

if __name__ == "__main__":

    from time import time
    from sys import argv
    from random import randint
    alen = 100
    if len(argv) > 1:
        alen = int(argv[1])
    a = [randint(-100,100) for i in xrange(alen)]

    time0 = time()
    print find_maximum_subarray_bf(a)
    time1 = time()
    print find_maximum_subarray_dc(a)
    time2 = time()
    print "function 1:", time1-time0
    print "function 2:", time2-time1 
    print "ratio:", (time1-time0)/(time2-time1)