算法学习历程---动态规划(一)

1.问题引入:求斐波那契数列第n项

  斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。
  指的是这样一个数列:1、1、2、3、5、8、13、21、34、……
  在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)


2.递归方法

def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fib(n - 1) + fib(n - 2)

用递归的好处就是简单,但是可以看大到,递归有很多重复计算。

比如,当n=4时,
fib(4)=fib(3) + fib(2)
      =fib(2) + fib(1) + fib(1) + fib(0)
      =fib(1) + fib(0) + fib(1) + fib(1) + fib(0)

其中fib(1)就要计算3次,fib(0)要计算2次。

3.动态规划

 为了解决上述递归解法的重复计算问题,我们引入动态规划的解法

  动态规划(英语:Dynamic programming,简称 DP)是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
  动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。
  它的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。动态规划往往用于优化递归问题,
  例如上述的斐波那契数列,利用动态规划的思想可以减少计算量。通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,具有天然剪枝的功能,从而减少计算量,
一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
 
  因此,动态规划算法也可以说是 '记住求过的解来节省时间',该算法的核心就是记住已经解决过的子问题的解
解法一

def fib(n):
    memo = [-1] * (n + 1)
    memo[0] = 0
    memo[1] = 1

    for i in range(2, n + 1):
        memo[i] = memo[i - 1] + memo[i - 2]
    return memo[n]

解法二

def fib(n):
    pre = 0
    next = 1
    i = 0
    while i != n:
        next += pre
        pre = next - pre
        i += 1
    return pre
posted @ 2019-12-18 20:23  渺渺兮予怀啊  阅读(124)  评论(0编辑  收藏  举报