第十题:斐波那契数列

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。

n<=39

 

难度:⭐⭐⭐⭐

关键:不能用递归,时间复杂度会以n的指数方式增长,导致stackoverflow。要用循环,为了计算量不大,要自下而上的循环,将运算结果存在中间变量中,这样就是O(n),以一定的空间代价避免代价更大的重复计算的栈空间浪费。

思路:从2开始。f(2)=f(1)+f(0)...one=1,two=0,for(;;){result=one+two;one=result;two=one}

其他:青蛙跳台阶(普通+变态版),矩形覆盖。运用了数学建模的分类思想。

关于动态规划三个条件:最优子结构、无后效性、子问题重叠。

 

我的。

class Solution {
public:
    int Fibonacci(int n) {
        //n<2时
        
        if(n<0) throw exception();
        else if(n<2) return n;
        else
        {
            int result=0;
            int first=1;
            int second=0; 
            for(int i=1;i<n;i++)
            {
                result=first+second;
                second=first;
                first=result;
            }
            return result;
        }

    }
};

 c++动态规划版

class Solution {
public:
    int Fibonacci(int n) {
        int f = 0, g = 1;
        while(n--) {
            g += f;
            f = g - f;
        }
        return f;
    }
};

 

python 。以数组的方式。

# -*- coding:utf-8 -*-
class Solution:
    def Fibonacci(self, n):
        # write code here
        res=[0,1,1,2]
        while len(res)<=n:
            res.append(res[-1]+res[-2])
        return res[n]

 其他题目 

青蛙跳台阶

class Solution {
public:
    int jumpFloor(int number) {
        if(number<=0) throw exception();
        if(number<=2)
            return number;
        else
        {
            //f(3)=f(2)+f(1)
            int one=2;
            int two=1;
            int result=3;
            for(int i=2;i<number;i++)
            {
                result=one+two;
                two=one;
                one=result;
            }
            return result;
        }
        
    }
};

python

# -*- coding:utf-8 -*-
class Solution:
    def jumpFloor(self, n):
        # write code here
        res=[1,1,2]
        while len(res)<=n:
            res.append(res[-1]+res[-2])
        return res[n]

青蛙跳台阶变态版

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

关于本题,前提是n个台阶会有一次n阶的跳法。分析如下:

f(1) = 1

f(2) = f(2-1) + f(2-2)         //f(2-2) 表示2阶一次跳2阶的次数。

f(3) = f(3-1) + f(3-2) + f(3-3) 

...

f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n) 

 

说明: 

1)这里的f(n) 代表的是n个台阶有一次1,2,...n阶的 跳法数。

2)n = 1时,只有1种跳法,f(1) = 1

3) n = 2时,会有两个跳得方式,一次1阶或者2阶,这回归到了问题(1) ,f(2) = f(2-1) + f(2-2) 

4) n = 3时,会有三种跳得方式,1阶、2阶、3阶,

    那么就是第一次跳出1阶后面剩下:f(3-1);第一次跳出2阶,剩下f(3-2);第一次3阶,那么剩下f(3-3)

    因此结论是f(3) = f(3-1)+f(3-2)+f(3-3)

5) n = n时,会有n中跳的方式,1阶、2阶...n阶,得出结论:

    f(n) = f(n-1)+f(n-2)+...+f(n-(n-1)) + f(n-n) => f(0) + f(1) + f(2) + f(3) + ... + f(n-1)

    

6) 由以上已经是一种结论,但是为了简单,我们可以继续简化:

    f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)

    f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2) + f(n-1) = f(n-1) + f(n-1)

    可以得出:

    f(n) = 2*f(n-1)

    

7) 得出最终结论,在n阶台阶,一次有1、2、...n阶的跳的方式时,总得跳法为:

              | 1       ,(n=0 ) 

f(n) =     | 1       ,(n=1 )

              | 2*f(n-1),(n>=2)

class Solution {
public:
    int jumpFloorII(int number) {
        // f(n) = 2*f(n-1)
        if (number <= 0) {
                return -1;
            } else if (number == 1) {
                return 1;
            } else {
                return 2 * jumpFloorII(number - 1);
            }
    }
};

python

# -*- coding:utf-8 -*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        a=[1,2,4,8]
        while(len(a)<number):
            a.append(a[-1]*2)
        return a[number-1]

 

 

小矩形覆盖大矩形

class Solution {
public:
    int rectCover(int number) {
        if(number<=2) return number;
        else
        {
            //f(3)=f(2)+f(1)
            //f(4)=f(3)+f(2)
            int one=2;
            int two=1;
            int result=3;
            for(int i=2;i<number;i++)//3
            {
                result=one+two;
                two=one;
                one=result;
            }
            return result;
        }
    }
};

python

# -*- coding:utf-8 -*-
class Solution:
    def rectCover(self, number):
        # write code here
        a=[0,1,2,3]
        while(len(a)<=number):
            a.append(a[-1]+a[-2])
        return a[number]

 

posted @ 2018-07-18 23:01  lightmare  阅读(197)  评论(0编辑  收藏  举报