递归之汉诺塔
def hanoi(n,a,b,c): # n个盘子,a,b,c三根柱子
if n>0:
hanoi(n-1,a,c,b) # 第一步 ,将a上的n-1个盘子借助c移动到b
print('%s--->%s'%(a,c)) # 第二步,将第n个盘子从a移动到c
hanoi(n-1,b,a,c) # 第三步,将b上的n-1个盘子借助a移动到c
啥是动态规划?(递推)
例如:斐波那契序列的非递归法
def fib(n):
if n==1 or n==2:
return 1
alist=[0,1,1]
for i in range(3,n+1):
alist.append(alist[i-1]+alist[i-2])
return alist[-1]
动态规划有啥好处?
递归执行效率低:子问题的重复计算(斐波那契递归比非递归慢)
# fib(1)=1 , fib(2)=2
# fib(3)=fib(1) + fib(2)
# fib(4)=fib(2) + fib(3)
# fib(5)=fib(3) + fib(4)
# fib(6)=fib(4) + fib(5)
def fib(n):
if n==1 or n==2:
return 1
else:
return fib(n-1)+fib(n-2)
1. 最长公共子序列(LCS,子序列:可以不连续,子串:连续)
① 最长公共子序列的长度
# 最长公共子序列的长度
def LCS_lenth(x,y):
m=len(x)
n=len(y)
c=[[0 for _ in range(n+1)] for _ in range(m+1)] # 初始化一个二维列表
for i in range(1,m+1):
for j in range(1,n+1):
if x[i-1]==y[j-1]: # x,y的下标是从0开始的
c[i][j]=c[i-1][j-1]+1
else:
c[i][j]=max(c[i-1][j],c[i][j-1])
return c[m][n]
② 最长公共子序列 (根据上方的图记录最大值是来自于哪个方向,然后从最后回溯)
def LCS(x,y):
m=len(x)
n=len(y)
c=[[0 for _ in range(n+1)]for _ in range(m+1)]
b=[[0 for _ in range(n+1)]for _ in range(m+1)] # 用来记录表中箭头,1表示来自于左上,2表示来自于上方,3表示来自于左
for i in range(1,m+1):
for j in range(1,n+1):
if x[i-1]==y[j-1]:
c[i][j]=c[i-1][j-1]+1
b[i][j]=1 # 1:来自于左上
elif c[i-1][j]>c[i][j-1]:
c[i][j]=c[i-1][j]
b[i][j]=2 #来自于上
else:
c[i][j]=c[i][j-1]
b[i][j]=3 # 来自于左
return b
def LCS_traceback(x,y):
b=LCS(x,y)
i=len(x)
j=len(y)
result=[]
while i>0 and j>0:
if b[i][j]==1:
result.append(x[i-1])
i-=1
j-=1
elif b[i][j]==2:
i-=1
else:
j-=1
return ''.join(reversed(result))