数据结构之动态规划 斐波那契数列

$fib()$递归

$fib(n)=fib(n-1)+fib(n-2): {0, 1, 1, 2, 3, 5, 8, ……}$

复杂度计算

$T(0)=T(1)=1; T(n)=T(n-1)+T(n-2)+1, n>1$

令$S(n)=\frac{T(n)+1}{2}$//这是要去掉递归式里的常数

则$S(0)=1=fib(1), S(1)=1=fib(2)$

故$S(n)=S(n-1)+S(n-2)=fib(n+1) //\Phi=\frac{1+\sqrt{5}}{2}=1.61803……$

$T(n)=2*S(n)-1=2*fib(n+1)-1=O(fib(n+1))=O(\Phi ^n)=O(2^n)$

已知$\Phi^{36}=2^{25}, \Phi^{5}=10, (2^{10})^3=(10^3)^3$

$\Phi^{43}=2^{30}=10^9flo=1 sec$

$\Phi^{67}=10^14flo=10^5 sec=1 day$

递归跟踪后,先后出现递归实例$O(\Phi ^n)$个,去重后总数不超过$O(n)$种

面对递归实例爆炸而去重后数目并不多的现象,可以将已计算过的结果存下,也可以自下而上迭代

f=0;g=1;

while(0<n - - ){

  g = g + f;

  f = g - f;

}

return g;

(g=1,f=0;g=1,f=1;g=2,f=1;g=3,f=2;g=5,f=3;g=8,f=5;g=13,f=8……)

动态规划求解

原问题拆成若干子问题,保存子问题的解(不用多次重复求解)

public static int fib_dp(int n){
        if(n==0){
            return 0;
        }
        if(n == 1 || n == 2){
            return 1;
        }
        int pre = 1;
        int ppre = 1;
        int result = 0;
        for(int i=3; i<=n; i++){
            result = pre + ppre;
            ppre = pre;
            pre = result;
        }
        return result;
    }

来自myf008

应用:爬楼问题

一段楼梯有8级台阶,规定每一步可跨1级2级或3级,要登上第8级台阶,有几种不同的走法(从第1级开始)

第1级:梦开始的地方

到第2级:只跨1步,有1种。

到第3级:(1、1),(2),有2种。

到第4级:(1、1、1),(1、2),(2、1),有1+2=3种。

到第5级:(1、1、1、1),(1、1、2),(2、1、1),(2、2),(1、2、1),有2+3=5种。

到第6级:有3+5=8种。(从第4次开始,后一种情况总是前两种情况的和。)

到第7级:有5+8=13种。

到第8级:有8+13=21种。

 

动态规划求解最长公共子序列:

 

 

时间复杂度:

由于只需要填一个m行n列的二维数组,其中m代表第一个字符串长度,n代表第二个字符串长度,所以时间复杂度为O(m*n)

来自z-k

posted @ 2022-11-15 19:46  asandstar  阅读(40)  评论(0编辑  收藏  举报