斐波那契数列面试题解法(java)

斐波那契数列经常出现在程序员面试的题目中,本文总结一下斐波那契数列的解法
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)

题目1:给定整数N,代表台阶数,小明一次可以上一个台阶或一次上两个台阶(因为怕扯着蛋,一次最多上两个台阶),问上N节台阶总共有多少种方法?
问题分析:记f(n)表示上n节台阶的所有方法总数。小明初始站在第0级台阶上,f(0)=1;上第一节台阶,只能一次上去,f(1) = 1;小明上楼梯时要么经过第一级台阶,要么越过第一级台阶(越过第一级台阶只能站第二级台阶上),所以经过一步之后问题变成f(n) = f(n-1) + f(n-2)。f(n-1)表示站在第一级台阶上还剩多少种走法,f(n-2)表示站在第二级台阶上还是多少种走法。

题目2:假设农场中成熟的母牛每年只会生1头小母牛,并且永远不会死。第一年农场有1只成熟的母牛,从第二年开始,母牛开始生小母牛。给定整数N,求出N年后牛的数量。

题目3:我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?
详见http://hihocoder.com/problemset/problem/1143

计算结果一般很大,有时面试时需要使用BigInteger来表示。有时也会让结果mod一个数输出,这里假设mod19999997作为结果输出。

首先根据定义轻松写出暴力递归的代码

import java.util.Scanner;

class Fibonacci{
    //int能表示的最大值的一半,两个小于halfMax的值相加结果不会越界
    private static int halfMax = Integer.MAX_VALUE>>1;
    //求斐波那契数列第n项,结果对m求余
    public static int fibonacci(int n,int m)
    {
        if(n<1)
            return 0;
        if(n==1 || n==2)
            return 1;
        if(m<=halfMax){
            int result = fibonacci(n-1,m) + fibonacci(n-2,m);
            //return result%m;
            //本来应该进行求余操作,由于result不会大于2m,这里用减法速度回更快
            return result>=m?result-m:result;
        }
        else{
            long result = (long)fibonacci(n-1,m) + fibonacci(n-2,m);
            return (int) (result>=m?result-m:result);
        }           
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        System.out.println(Fibonacci.fibonacci(n, 19999997));
    }
}

面试的时候写成这样肯定是不合格的,这样写的时间复杂度为2的n次方,计算30以内的还可以,更大的数就需要等待了。通过分析可以发现计算中有大量重复的计算,比如f(n-2),计算f(n)的时候计算一次,计算f(n-1)的时候又计算一次。可以通过建立缓存来解决重复计算问题。代码如下

import java.util.Scanner;

class Fibonacci{
    //int能表示的最大值的一半,两个小于halfMax的值相加结果不会越界
    private static 
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值