python最大子序列和(连续)——分而治之

目录

分而治之思想:

最大子序列和问题描述:

问题解决思路:

问题解决代码:

算法复杂度分析:


分而治之思想:

#1将问题分解为若干简单的子问题

#2通过递归寻求各个子问题的的解

#3合并各个子问题的解,从而得到原始问题的解

最大子序列和问题描述:

给定N个整数的序列{A1,A2,...,AN},求函数f(i,j)=max(0,Ai+...+Aj)的最大值

问题解决思路:

现将序列等分为左右两份,则最大子列只可能出现在三个地方:

1整个子序列出现在左半部分

2整个子序列出现在右半部分

3整个子序列跨越中间边界

前两种情况可以用递归求解,而第三种情况则可以将前半部分的最大子序列和(此处的子序列必须包含前半部分的最后一个元素)后半部分的最大子序列和(此处的子序列必须包含后半部分的第一个元素)相加得到

注1:因为第三种情况跨越了中间边界,且要求的序列为连续的,因此第三种情况得到的子序列必定包含左子序列的最后一个元素以及右子序列的第一个元素。

注2:若要求的序列可以为不连续的,则第三种情况可以直接用前半部分最大子序列和与后半部分最大子序列和相加得到

问题解决代码:

def findMaxSum(A):
    #非常关键,否则会报错“超过最大递归深度”
    if len(A)<=1:
        return A[0]

    mid=len(A)//2
    leftA=A[:mid]
    rightA=A[mid:]

    leftMaxSum=findMaxSum(leftA)#递归求左边的最大序列和
    leftAfinal = 0#用于包含左边最后一个数的累加求和
    #考虑到存在序列全为负数的情况,因为初始化为负无穷而非0
    leftAfinalMax = -float('Inf')#包含左边最后一个数的最大序列和
    for i in range(0,len(leftA))[::-1]:
        leftAfinal=leftAfinal+leftA[i]
        if leftAfinal>leftAfinalMax:
            leftAfinalMax=leftAfinal

    rightMaxSum=findMaxSum(rightA)#递归求右边的最大序列和
    rightAfinal = 0#用于包含右边第一个数的累加求和
    #考虑到存在序列全为负数的情况,因为初始化为负无穷而非0
    rightAfinalMax = -float('Inf')#包含右边第一个数的最大序列和
    for j in range(0,len(rightA)):
        rightAfinal=rightAfinal+rightA[j]
        if rightAfinal>rightAfinalMax:
            rightAfinalMax=rightAfinal

    crossMaxSum = leftAfinalMax + rightAfinalMax
    return max(leftMaxSum, rightMaxSum, crossMaxSum)
A=[2,3,4,1,-1,7,-3,7,-6]

print(findMaxSum(A))
 

算法复杂度分析:

令T(N)为求解大小为N的最大子序列和问题所花费的时间,则求解左子序列和右子序列花费的时间分别为T(N/2),在求解第三种情况时,可以看到以上程序中两个for循环次数相加为N,因此两个for循环总共的时间复杂度为O(N)。

综上,以上程序花费的总时间为:

T(N)=2\ast T(N/2)+c\ast N,且T(1)=O(1)

利用上式递归代入有:T(N)=2[2T(\frac{N}{2^{2}})+c\frac{N}{2}]+cN

直至当N除以k次2时有\frac{N}{2^{k}}=1,此时为递归的终点,此时中括号外会乘以k个2, 即2^{k},一共k个cN,所以有:

2^{k}*O(1)+ckN=O(NlogN)

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值