浙大_数据结构_1:最大子列和


最近开始学数据结构,用的最简单的python进行实现,记录一下学习过程

算法一:穷举法

1.算法描述:利用三个for循环遍历所有可能的子列并求和

2.算法实现:

#A为列表,N为列表长度
def f1(A, N):
    MaxSum = 0
    for i in range(N):
        for j in range(i, N):
            ThisSum = 0
            for k in range(i, j):
                ThisSum += A[k]
            if ThisSum > MaxSum:
                MaxSum = ThisSum
    return MaxSum

时间复杂度 T ( N ) = O ( N 3 ) T(N) = O(N^3) T(N)=O(N3)

算法二:穷举法优化

1.算法描述:依旧需要算出所有的子列和,但是在算以List[i]为起点,List[j]为终点的子列和的时候,可以依据计算的上一个子列(以List[i]为起点,List[j-1]为终点)的和来计算,即:当前子列和 = 上一个子列和 + List[j]。

2.算法实现:

def f2(A, N):
    MaxSum = 0
    for i in range(N):
        ThisSum = 0
        for j in range(i, N):
            ThisSum += A[j]
            if ThisSum > MaxSum:
                MaxSum = ThisSum
    return MaxSum

时间复杂度 T ( N ) = O ( N 2 ) T(N) = O(N^2) T(N)=O(N2)

算法三:分而治之

1.算法描述:把数列分成左右两部分。最大子序列和的位置存在三种情况:

1)完全在左半部分;
2)完全在右半部分;
3)跨越左右两部分。

分别求出左半部分的最大子序列和、右半部分的最大子序列和、以及跨越左右两部分的最大子序列和,三者中的最大者就是该数列的最大子列和。

求左、右半部分最大子列和求法:把左、右半部分分别作为新的输入序列通过该算法递归求出。

跨越左右两部分的最大子序列和求法:求出左半数列中包含左半数列最右元素所有子列中和最大的一个,并求出右半数列中包含右半数列最左元素所有子列中和最大的一个,两者和相加,即是跨越左右两部分的最大子序列和。

如图:
分治图解
对于每个切分出来的子列都求左、跨、右子列的和最大值,再向上传递。

2.算法实现:

def f3(A, N):
    if N != 1:
        if N % 2 == 0:
            LeftSum = f3(A[:int(N/2)], int(N/2))  #-1
            RightSum = f3(A[int(N/2):], int(N/2)) #5
            MidSum = f3_mid(A, int(N/2), N)  #4
        else:
            LeftSum = f3(A[:int(N/2)], int(N/2))  #4
            RightSum = f3(A[int(N/2):], int(N/2)+1)   #5
            MidSum = f3_mid(A, int(N/2), N)    #8

        MaxSum = LeftSum

        if RightSum > MaxSum:
            MaxSum = RightSum
        elif MidSum > MaxSum:
            MaxSum = MidSum
        return MaxSum

    else:
        return A[0]

其中跨左右的子列和的函数f3_mid()如下:

#N1为前半段子列长,N为总长
def f3_mid(A, N1, N):
    Mid_LeftSum = A[N1 - 1]
    Sum = 0
    for i in range(N1-1, -1, -1):
        Sum += A[i]
        if Sum > Mid_LeftSum:
            Mid_LeftSum = Sum

    Sum = 0
    Mid_RightSum = A[N1]
    for i in range(N1, N):
        Sum += A[i]
        if Sum > Mid_RightSum:
            Mid_RightSum = Sum

    return Mid_LeftSum + Mid_RightSum

时间复杂度 T ( N ) = O ( N l o g N ) T(N) = O(NlogN) T(N)=O(NlogN)

算法四:在线处理

1.算法描述:
遍历整个数组,扫描时将扫描点累加,并将累加值与最大子列和比较,如果大于最大子列和,这更新最大子列和。如果累加之后结果为负数,将累加和置零,并从下一扫描点开始累加,因为负数与后面的扫描点的值相加,并不能使累加和变得更大。

在线的意思是指每输入一个数据就进行即时处理 ,在任何一个地方终止输入,算法都能能正确给出当前解。

2.算法实现:

def f4(A, N):
    ThisSum = 0
    MaxSum = 0
    for i in range(N):
        ThisSum += A[i]
        if ThisSum > MaxSum:
            MaxSum = ThisSum
        elif ThisSum < 0:
            ThisSum = 0
    return MaxSum

时间复杂度 T ( N ) = O ( N ) T(N) = O(N) T(N)=O(N)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值