ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

<算法导论>练习4.1

2021-03-25 20:02:15  阅读:171  来源: 互联网

标签:__ 4.1 max sum 导论 high 算法 low ans


4.1-1
所有元素都是负数时,最大子数组的和就是A中最大的元素。所有程序会返回A中最大的数。

4.1-2
两个for循环嵌套,且最大迭代次数是n,时间复杂度是 Θ ( n 2 ) \Theta(n^2) Θ(n2)

def find_maximum_subarray(a):
    n=len(a)
    max_sum=-float('inf')
    low=0;high=0
    for i in range(n):
        sum_da=0
        for j in range(i,n):
            sum_da+=a[j]
            if sum_da>max_sum:
                max_sum=sum_da
                low=i
                high=j
    return low,high,max_sum

if __name__ == '__main__':
    a=[13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7]
    l,h,ma=find_maximum_subarray(a)
    print('最大子数组范围',[l,h])   # python里列表下标从0开始
    print('最大和为:',ma)

4.1-3
在我的笔记本电脑上, n 0 n_0 n0​是35.混合的方法交叉点会好一些。

4.1-4
计算完成后,若得出的最大子数组的和小于0,返回空数组即可。

4.1-5
没有按照题目中所说的方法,思想是:如果某一段序列A[i…j]的和求出来是小于0的,那么包含这一段的新序列B[m,…i…j…n]肯定比不包含它要小,如果A在B的端点处,那么B可以直接舍弃A。每个元素操作一次,复杂度为 Θ ( n ) \Theta(n) Θ(n)

def find_maximum_subarray(a):
    n=len(a)
    max_sum=-float('inf')
    sum_a=-float('inf')
    c_high=0;c_low=0
    low=0;high=0
    for j in range(n):
        c_high=j
        if sum_a>0:
            sum_a+=a[j]
        else:
            c_low=j
            sum_a=a[j]
        if sum_a>max_sum:
            max_sum=sum_a
            low=c_low
            high=c_high
    return low,high,max_sum

if __name__ == '__main__':
    a=[13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7]
    l,h,ma=find_maximum_subarray(a)
    print('最大子数组范围',[l,h])   # python里列表下标从0开始
    print('最大和为:',ma)

有一种更一般的求最大子序和的问题是规定子序的长度不能超过M,对于这个问题上面的做法就不适用了,更通用的方法是“前缀和+单调队列”的方法来做。
前缀和:若已知A[1,2,…n],可以计算出其前缀和S[1,…n],其中:
S [ i ] = A [ 1 ] + A [ 2 ] + . . . + A [ i ] S[i]=A[1]+A[2]+...+A[i] S[i]=A[1]+A[2]+...+A[i]
那么A[i,…j]这一段的子序和就等于S[j]-S[i-1].

单调队列:即队列中存储的序列是单调的,那么在取出其中的最值时只需要O(1)的操作。

def find_maximun_subarray(matrix,m):
    n=len(matrix)
    s = [0 for _ in range(n + 1)]
    q = [0 for _ in range(n + 1)]
    #求前缀和
    for i in range(n):
        s[i + 1] = s[i] + matrix[i]
    # print(s)

    ans = -float('inf')
    l = 0;
    r = 0  # 队列的左右端点
    for i in range(1, n + 1):
        if i - q[l] > m:
            l += 1
        ans = max(ans, s[i] - s[q[l]])
        # print('i=',i,'q=',q,'q[l]=',q[l],'ans=',ans,'q[r]= ',q[r],'l=',l,'r=',r)
        while l <= r and s[q[r]] >= s[i]:
            r -= 1
        r = r + 1
        q[r] = i
    return ans
if __name__ == '__main__':
    m=5   # 最大子序长度,
    a = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
    ans=find_maximun_subarray(a,m)
    print(ans)

其中m是规定的最大子序长度,当 m > = A . l e n g t h m>=A.length m>=A.length时,就是书中例题的样子了。

标签:__,4.1,max,sum,导论,high,算法,low,ans
来源: https://blog.csdn.net/a1121420/article/details/115208396

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有