整理一下近期写的代码:
经典子序列的问题:
给定一个列表,求出和最大的一个连续子序列
my_num=8
my_arr=[-2,6,-1,5,4,-7,2,3]
#最大子序列(是连续的)
# 暴力循环
# 初始化最大和列表的第一个元素
# 三层循环
def method1(Num,arr):
ans = arr[0]
for i in range(Num):
for j in range(i,Num):
s=0
for k in range(i,j+1):
s+=arr[k]
if s>ans:
ans=s
print(ans)
# 简单的优化,先求出一个和数组
def method2(Num,arr):
sum=[-float('Inf') for i in range(Num+1)]
sum[0],ans=0,arr[0]
for i in range(1,Num):
sum[i]=arr[i]+sum[i-1]
for i in range(1,Num+1):
for j in range(i,Num+1):
if sum[j]-sum[i-1]>ans:
ans=sum[j]-sum[i-1]
print(ans)
# 第三种递归实现
def findMaxSum(arr,left,right):
# 设置终止条件
# 分组
if left==right:
return arr[left]
mid=(left+right)//2
leftMaxSum=findMaxSum(arr,left,mid)
rightMaxSum=findMaxSum(arr,mid+1,right)
left_max,right_max,temp=-float('Inf'),-float('Inf'),0
for i in range(mid,left-1,-1):
temp+=arr[i]
if temp>left_max:
left_max=temp
temp=0
for i in range(mid+1,right+1):
temp+=arr[i]
if temp>right_max:
right_max=temp
cross_max=left_max+right_max
return max(leftMaxSum,rightMaxSum,cross_max)
#动态规划1 递推公式
# dp[n] = max(0, dp[n-1]) + arr[n]
def method4(arr):
dp=arr[:]
maxvalue,start,end=arr[0],0,0
for n in range(1,len(arr)):
if dp[n-1]>0:
dp[n]=dp[n-1]+arr[n]
else:
dp[n]=arr[n]
start=n
if dp[n]>maxvalue:
maxvalue=dp[n]
end=n
print(maxvalue,arr[start:end+1])
# 动态规划2:可以标识起始点
# sum(j)=max(sum(j-1)+aj,aj)
def method5(arr):
maxvalue,temp,begin,end=0,0,0,0
for i in range(len(arr)):
if temp>0:
temp+=arr[i]
else:
temp=arr[i]
begin=i
if temp>maxvalue:
maxvalue=temp
end=i
print(maxvalue,arr[begin:end+1])
连续递增的子序列(动态规划法):
my_num=8
my_arr=[0,1,2,3,-1,0,1,2,3,-4,-5]
#最长连续递增序列
def method1(arr):
temp,maxl,end=1,0,0
for i in range(1,len(arr)):
if arr[i]>arr[i-1]:
temp+=1
else:
temp=1
if temp>maxl:
maxl=temp
end=i
print(maxl,arr[end+1-maxl:end+1])
# method1([1,9,2,5,7,3,4,6,8,0,11,15,17,17,10])
# 求最长公共子序列,可以不连续
# 动态规划
def LCS(arr1,arr2):
len1,len2=len(arr1),len(arr2)
vals=[[0 for i in range(len2+1)] for j in range(len1+1)]
#新建一个方向列表,用于回溯
directions = [[None for i in range(len2+1)] for j in range(len1+1)]
for i in range(len1):
fi=i+1
for j in range(len2):
fj=j+1
if arr1[i]==arr2[j]:
vals[fi][fj]=vals[i][j]+1
directions[fi][fj]='ok'
elif vals[i][fj]>vals[fi][j]:
vals[fi][fj] = vals[i][fj]
directions[fi][fj]='top'
elif vals[i][fj]<=vals[fi][j]:
vals[fi][fj]=vals[fi][j]
directions[fi][fj] = 'left'
maxNum=vals[len1][len2]
(row,col)=(len1,len2)
commons=[]
while directions[row][col]:
if directions[row][col]=='ok':
commons.append(arr1[row-1])
row-=1
col-=1
elif directions[row][col]=='top':
row-=1
elif directions[row][col]=='left':
col-=1
output=commons[::-1]
return (maxNum,output)
print(LCS([2,3,4,0,1,3],[0,1,2,3,3,4]))
不足之处:如果存在多个最大公共子列,输出其中一个。输出全部的有待进一步优化。