剑指Offer题目9:斐波那契数列(Java)

面试题9:你们都知道斐波那契数列,如今要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39面试

Basic :斐波那契数列定义

当 0 < n <= 1 时,f(n) = n;
当 n > 1 时,f(n) = f(n-1) + f(n-2)
复制代码

解题思路

1、递归写法(低效,慢)bash

递归分析,以下图所示:ui

这棵树中有不少结点是重复的,并且重复的结点数会随着n的增大而急剧增长,这意味计算量会随着n的增大而急剧增大。spa

用递归方法计算的时间复杂度是以n的指数的方式递增的。code

2、for 循环写法cdn

使用中间变量,在每次循环以后都将中间计算结果保存起来,用于下一次循环,时间复杂度减小到O(n)。blog

代码实现

1、递归写法(低效,慢)递归

public class Solution {
    public int Fibonacci(int n) {
        if(n <= 1) {
            return n;
        }
        return Fibonacci(n-1) + Fibonacci(n-2);
    }
}
复制代码

2、for 循环写法ci

public class Solution {
    public int Fibonacci(int n) {
        if(n <= 1) {
            return n;
        }
        int fibNMinus1 = 1;
        int fibNMinus2 = 0;
        int fibN = 0;
        for(int i=2; i<=n; i++){
            fibN = fibNMinus1 + fibNMinus2;
            fibNMinus2 = fibNMinus1;
            fibNMinus1 = fibN;
        }
        return fibN;
    }
}
复制代码

总结

递归实现起来简洁,但一般效率比for循环要低不少。get

扩展:青蛙跳台阶

题目:一只青蛙一次能够跳上1级台阶,也能够跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(前后次序不一样算不一样的结果)。

思路分析

前提只有 一次 1阶或者2阶的跳法。

a.若是两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);

b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)

c.由a和b 两种假设能够得出总跳法为: f(n) = f(n-1) + f(n-2) 

d.Base case:只有一阶的时候 f(1) = 1 ,只有两阶的时候能够有 f(2) = 2
复制代码
public class Solution {
    public int JumpFloor(int target) {
        if(target <= 0) {
            return -1;
        }
        if(target <= 2){
            return target;
        }
        return JumpFloor(target - 1) + JumpFloor(target - 2);
    }
}
复制代码

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

数学概括法,各类计算,略过。

题目:咱们能够用2×1(图2.13的左边)的小矩形横着或者竖着去覆盖更大的矩形。请问用8个2×1的小矩形无重叠地覆盖一个2×8的大矩形(图2.13的右边),总共有多少种方法?

思路分析

首先把 2x8 的覆盖方法总数记为 f(8)。

用第一个 1x2 小矩形去覆盖大矩形的最左边时有两个情形,竖着放或者横着放。

竖着放:右边还剩下 2x7 的区域,这种情形下的覆盖方法记为 f(7)。

横着放:1x2 小矩形无论是横着放在左上角仍是左下角,另一个小矩形必须跟在该小矩形的下边或上边贴合,即不管如何只有
一种覆盖方法。而此时右边还剩下 2x6 的区域,这种情形下的覆盖方法记为 f(6)。

2x8 的覆盖方法就由这两种情形构成,所以,他们之间存在如下关系:

f(8) = f(7) + f(6)

类推:f(n) = f(n-1) + f(n-2) 即斐波那契数列。
复制代码

代码实现

public class Solution {
    public int RectCover(int target) {
        if(target<=2) {
            return target;
        }
        return RectCover(target - 1) + RectCover(target - 2);
    }
}
复制代码
相关文章
相关标签/搜索