首先通过斐波那契数列引出两个概念
斐波那契数列:
已知f(0)=0, f(1)=1, f(n)= f(n-1)+ f(n+2)分别用两种不同的思想求得 f(n)。
1.递归:
解决递归问题,首先要明确函数定义,然后寻找递归终止条件,最后要能够准确的写出递归子式,即明确递归过程。
def F(n):
if n == 0:
return 0
if n == 1:
return 1
return F(n-1) + F(n-2)
但在上述递归代码中有好多是会重复计算的,为了改进,可以将已经计算的结果保存下来,这就引出了记忆化搜索;
2.记忆化搜索:
将记忆化搜索通过代码的方式实现,结果如下:
mery = [-1]*(n+1)
def new_f(n):
if n == 0:
return 0
if n == 1:
return 1
if mery[n] == -1:
mery[n] = new_f(n-1) + new_f(n-2)
return mery[n]
3.动态规划:
斐波那契数列用动态规划的思想解决的话,代码如下:
def dp(n):
mery = [-1]*(n+1)
for i in range(0, n+1):
if i == 0:
mery[i] = 0
elif i == 1:
mery[i] = 1
else:
mery[i] = mery[i-1] + mery[i-2]
return mery[n]
4.动规和递归的总结:
此时,仔细品两种做法,以斐波那契数列问题为例,发现f(n)和前两项有关,递归的做法是从f(n)开始,不断去求前一项,直至满足递归终止条件;再看动态规划,同样发现发现f(n)和前两项有关,动规的做法是从第一项开始求,直至求得第n项。
两者的主要区别:两者最大的区别是思考问题的方式不同,递归是一种自上而下的思考方式,递归是一种自下而上的思考方式。当递归层数过深的话,容易产生堆栈溢出的问题。
5.实战问题分析:
以青蛙变态跳台阶问题为例:
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。(题目来源于牛客网)
首先看递归的做法:
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
mery = [-1]*(number+1)
def dp(n):
if n == 1 or n == 0:
return 1#递归终止条件
if mery[n]==-1:
tmp = 0
for i in range(1,n+1):
tmp += dp(n-i)
mery[n] = tmp
return mery[n]
return dp(number)
再看动规的做法:
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, n):
# write code here
dp = [0]*(n+1)
dp[0] = 1
for i in range(1,n+1):
tmp = 0
for j in range(0,i):
tmp += dp[j]
dp[i] = tmp
return dp[n]