【剑指offer-java版】7、斐波那契数列问题合集:跳台阶/变态跳台阶/矩形覆盖

时间限制:1秒  空间限制:32768K  热度指数:296927

题目描述

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

n<=39

解题思路

方法一:递归

斐波那契数就是 1 1 2 3 5 8……每一项都等于前两项之和,刚开始学编程语言时就会想到递归,但是如果n非常大的时候,很容易stack overflow,由于本题n<=39的,所以还是通过了,但还是仅做对比就好。我觉得能递归的问题一般都是可以动态规划的 >///<

代码:

import java.util.*;
public class Solution {
    public int Fibonacci(int n) {
        int one=1;
        int two=1;
        if(n==0){
            return 0;
        }else if(n==1||n==2){
            return 1;
        }else
            return Fibonacci(n-1)+Fibonacci(n-2);
        }
}

运行时间:627ms

占用内存:9436k


方法一:动态规划

动态规划我一直觉得本质就是把递归反过来,斐波那契的每一项都仅仅依赖于前两项,通过以后看到别人的代码还有每次i++进行for循环的,相比起来i+2循环次数少,效率更高,因此运行时间短。

如果n不能被2整除,则返回那次循环中的第一个数,如果能被2整除则返回第二个。

【下面的代码是我尝试的时间最短的方法,如果有其他时间复杂度或者空间复杂度更优的解法欢迎讨论】

代码:

import java.util.*;
public class Solution {
    public int Fibonacci(int n) {
        int one=1;
        int two=1;
        if(n==0){
            return 0;
        }
        for(int i=3;i<=n;i=i+2){
            one=one+two;
            two=one+two;
        }
        if(n%2==0){
            return two;
        }else{
            return one;
        }
    }
}

运行时间:11ms

占用内存:9268k

===============================================================

斐波那契数列扩展——跳台阶问题

时间限制:1秒  空间限制:32768K  热度指数:228625

题目描述

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

解题思路

假如一只青蛙要跳到第10阶台阶,那么它有可能是从9跳上来的,9到10只有一种跳法;还有可能是从8跳上来的,8到10有一种跳法。
如果用f(n)表示青蛙跳到第n阶的方法数,那么青蛙跳到第10阶有f(9)*1+f(8)*1种跳法,那么就可以得到 状态转移方程 f(n)=f(n-1)+f(n-2);
因此每一个状态只依赖于之前的两个状态。

当青蛙要跳到1阶时只有一种跳法,跳到2阶时有两种跳法,所以 f(1)=1,f(2)=2

由此可以看出青蛙跳方法问题其实就是一个斐波那契数列,同样可以使用递归或者动态规划。(递归重复计算太多,不建议)

动态规划:

public class Solution {
    public int JumpFloor(int target) {
        //f(n)=f(n-1)+f(n-2)
        int one=1;
        int two=2;
        if(target<3){
            return target;
        }
        for(int i=3;i<=target;i+=2){
                one=one+two;
                two=one+two;
            }
        if(target%2==0){
            return two;
        }else{
            return one;
        }
    }
}

运行时间:11ms

占用内存:9160k

递归:

public class Solution {
    public int JumpFloor(int target) {
        //f(n)=f(n-1)+f(n-2)
        
        if(target==1){
            return 1;
        }else if(target==2){
            return 2;
        }else
            return JumpFloor(target-1)+JumpFloor(target-2);
    }
}

运行时间:513ms

占用内存:9304k

题外话:看到别的筒子有使用i++循环的,我也对运行时间和内存进行了测试,运行时间基本是在11ms-20ms不等,相差不是很多,可能是因为我的写法中虽然i+2减少了循环次数,但是判断n是否能被2整除时会花费一点时间。我觉得在n非常大时递归肯定是不推荐的,可能会stack overflow,i+2这样的循环较少的写法还是更好一些。

===============================================================

跳台阶扩展——变态跳台阶问题

时间限制:1秒  空间限制:32768K  热度指数:177799

题目描述

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

解题思路

青蛙跳到n阶有f(n)=f(n-1)+f(n-2)+f(n-3)+……+f(1)中跳法,

而跳到n-1阶有f(n-1)=f(n-2)+f(n-3)+……+f(1)种跳法,代入上式得

f(n)=2*f(n-1),每一个台阶的跳法只依赖于上一个状态

而青蛙跳到1阶有f(1)=1种跳法,跳到2阶有f(2)=2种跳法也满足f(n)=2*f(n-1)

依然是可以用递归或者动态规划

 递归:

public class Solution {
    public int JumpFloorII(int target) {
        if(target==1){
            return 1;
        }else
            return 2*JumpFloorII(target-1);
    }
}

运行时间:19ms

占用内存:8684k

动态规划:

public class Solution {
    public int JumpFloorII(int target) {
        //f(n-1)=f(n-2)+f(n-3)+……+f(1)+f(0)
        //f(n)=f(n-1)+f(n-2)+f(n-3)+……+f(1)+f(0)=2*f(n-1)
        int temp=1;
        if(target==1){
            return temp;
        }else{
            for(int i=2;i<=target;i++){
                temp=2*temp;
            }
        }
        return temp;
    }
}

运行时间:18ms

占用内存:8828k


===============================================================

扩展-矩形覆盖

时间限制:1秒  空间限制:32768K  热度指数:157518

题目描述

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

解题思路

在word里画了个图方便描述:

因此可以归纳出f(n)=f(n-1)+f(n-2),就是一个斐波那契数列的应用,依然可以使用递归或者动态规划,但是用递归可能会出现栈溢出的现象

代码

 

public class Solution {     public int RectCover(int target) {         int one=1;         int two=2;         int t;         if(target==0||target==1||target==2){             return target;         }else              for(int i=3;i<=target;i++){                 t=one;                 one=two;                 two=one+t;             }         return two;     } }

运行时间:10ms

占用内存:9280k


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值