算法 --- 斐波那契数列的Java实现

1.概况   

     斐波那契数列(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*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。

2.Java实现

public class Test {

    public static void main(String[] args) {
     System.err.println(fibonacci(3)); // 2
    }

    public static int fibonacci(int n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        return fibonacci(n-1) + fibonacci(n-2);
    }
}

3.应用

1>在你面前有一个n阶的楼梯,你一步只能上1阶或2阶。请问,当N=11时,你可以采用多少种不同的方式爬完这个楼梯();当N=9时呢?

答: 144,55

当台阶只有一阶时,只能走一步,只有一种走法。

当两级台阶时,可以走一步,也可以一次走两步,有两种走法。

当三级台阶时,可以走一步,走三次。可以先走一步,再两步。也可以,先两步,再一步。总共三种方法。 可以看到当台阶是3时,第1级台阶选中之后(一种),剩下可以走的方式恰好是台阶为2时的总数,总的数量为前两个之和,所以是f(3)=f(1)+f(2)。即,f(n)=f(n-2)+f(n-1),总结起来刚好是一个斐波那契数列。

public class Test {

    public static void main(String[] args) {
     System.err.println(fibonacci(11) + "|" + fibonacci(9)); // 144|55
    }

    public static int fibonacci(int n) {
        if (n == 1) {
            return 1;
        } else if (n == 2) {
            return 2;
        } else {
            return fibonacci(n-1) + fibonacci(n-2);
        }
    }
}

2>剑桥offer之跳台阶

题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

解题思路:

第一阶有只能一步,一种;,第二阶可以两次一步、一次两步两种

  • 若楼梯阶级 n = 3
    • 跳 2 步到 3:剩下的是第一步没跳,起始跳到第一步只有一种
    • 跳 1 步到 3:剩下的是第二步没跳,起始跳到第二步有两种
  • 若楼梯阶级 n = n
    • 跳 2 步到 n:剩下的是第 n - 2 步没跳,起始跳到第 n - 2 步设它为 pre2 种
    • 跳 1 步到 n:剩下的是第 n - 1 步没跳,起始跳到第 n - 1 步设它为 pre1 种

Java源码实现:

public class Solution {
    public int JumpFloor(int target) {
         if (target == 1) return 1;
         if (target == 2) return 2;
         if (target == 3) return 3;
         return JumpFloor(target - 1) + JumpFloor(target - 2);
    }
}

3>剑桥offer之变态跳台阶

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

解题思路:

设n级台阶有f(n)种跳法,根据最后一次跳台阶的数目可以分解为最后一次跳一级,则前面需要跳n−1 级,有f(n−1)种跳法;最后一次跳两级,则前面需要跳n−2级,有f(n−2)种跳法。以此类推 易知,
f(n)=f(n−1)+f(n−2)+……f(0)

f(n−1)=f(n−2)+……f(0)

两式相减得,

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

Java源码实现:

public class Solution {
    public int JumpFloorII(int target) {
        return 1<<(target-1);
    }
}

4>剑桥offer之矩阵覆盖

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

解题思路(转载):

  • n = 1 的时候
    • 只能横着覆盖,一种
  • n = 2 的时候
    • 可以横着和竖着覆盖,两种
  • n = 3 的时候
    • 第三级横着覆盖,用了一级,剩下 n = 2,有两种覆盖方法
    • 第三季竖着覆盖,用了两级,剩下 n = 1,有一种覆盖方法
    • 总共有 3 种
  • n = 4 的时候
    • 第 4 级横着覆盖,用了一级,剩下 n = 3,有三种覆盖方法
    • 第 4 级竖着覆盖,用了两级,剩下 n = 2,有两种覆盖方法
    • 总共有 5 种方法
  • n = n 的时候
    • 第 n 级横着覆盖,用了一级,剩下 n = n - 1,所以关注第 n - 1 种有几种覆盖方法
    • 第 n 级竖着覆盖,用了两级,剩下 n = n - 2,所以关注第 n - 2 种有几种覆盖方法
    • 总和为两种情况的总和

从 n = 1 到 n = 4 的示意图如下:

所以回答上面的问题,涂掉最后一级矩阵的时候,可以选择使用横向完成,也可以使用竖向完成,横向涂剩下 n - 1 阶,竖向涂剩下 n - 2 阶

Java源码实现:

public class Solution {
    public int RectCover(int target) {
       if (target == 0) return 0;
       if (target == 1) return 1;
       if (target == 2) return 2;
       return RectCover(target - 1) + RectCover(target - 2);
    }
}
发布了42 篇原创文章 · 获赞 3 · 访问量 3931

猜你喜欢

转载自blog.csdn.net/zhangting19921121/article/details/103250422