一、递归和DP
1)递归
一般情况下,递归定义包含两部分,其中至少有一种基本情况可以直接得到在特定情况下的结果,还有一种递归或者归纳情形定义出在其他情况下的结果。
举一个简单的阶乘例子:
1!=1
(n+1)!=(n+1)*n!
第一个式子定义了基本情况,第二个式子定义了其余情况
那么我们下面用两段代码来比较一下迭代和递归
#迭代
def fact1(n):
result=1
while n>1:
result *=n
n -=1
return result
#递归
def fact2(n):
if n==1:
return n
else:
return n*fact2(n-1)
2)动态规划(DP)
动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。适用于解决具有重复子问题和最优子结构的问题。如果一个问题的全局最优解可以通过组合局部最优解求出那么这样的问题就存在最优子结构。例如归并排序,先对子列表进行排序,然后合并子列表的排序结果。
动态规划的核心思想是备忘录法,将递归中的调用结果保存下来,在需要时直接查找,而不是重新计算,这样就节省了大量的时间。
这里我们以一个斐波那契数列为例来简单对比一下。
#递归
def fib(n):
if n==0 or n==1:
return 1
else:
return fib(n-1)+fib(n-2)
#基于备忘录法
def fastFib(n,memo={}):
if n==0 or n==1:
return 1
try:
return memo[n]
except KeyError:
result=fastFib(n-1,memo)+fastFib(n-2,memo)
memo[n]=result
return result
我们在这里做一点简单的对比分析,递归法de复杂度和函数结果成正比,而斐波那契数列增长很快,复杂度大概是o(fib(n)),我们可以大概看一下后面增长速度,fib(1)=1;fib(2)=2;fib(3)=3;fib(b)=5;fib(120)=8e24;
现在来看目录法,对于0——n的没一个整数,他都只计算一次值。因此基于字典查找可以在常熟时间内完成。fastFib(n)复杂度为o(n)