浙大_数据结构_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
时间复杂度
算法二:穷举法优化
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
时间复杂度
算法三:分而治之
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
时间复杂度
算法四:在线处理
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
时间复杂度
上一篇: 从零使用强化学习训练AI玩儿游戏(2)——学习Gym
下一篇: spring boot 获取所有属性