Fibonacci 解题报告

Fibonacci

Description

Find the Nth number in Fibonacci sequence.

A Fibonacci sequence is defined as follow:

The first two numbers are 0 and 1.
The i th number is the sum of i-1 th number and i-2 th number.

The first ten numbers in Fibonacci sequence is:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ...

Notice
The Nth fibonacci number won’t exceed the max value of signed 32-bit integer in the test cases.

Example

If n = 15, you should return:

Given 1, return 0
Given 2, return 1
Given 10, return 34

实现思路

Fibonacci 方程满足f(i) = f(i-1) + f(i-2)
这里给出两种实现思路,一种是基于迭代,另一种则基于递归,基于递归又分为直接递归和尾递归。

实现方法1:基于迭代

注意好边界问题,确定返回pre而非cur,每次迭代需要使pre和cur前进一步。

/**
     * @param n: an integer
     * @return an integer f(n)
     */
    public int fibonacci(int n) {
        int pre = 0,cur = 1,tmp;
        for(int i = 1 ; i < n; i ++ ){
            cur += pre;
            pre = cur - pre; 
        }
        return pre;
    }

实现方法2:基于非尾递归

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

使用这个方法会超时,原因是每次计算fibonacci(n-1)或fibonacci(n-2)都需要重新计算一遍,类似过程如下所示:

Fib(6) = Fib(5) + Fib(4);
    = Fib(4) + Fib(3) + Fib(3) + Fib(2);
    = Fib(3) + Fib(2) + Fib(2) + Fib(1) + Fib(2) + Fib(1) + Fib(2);
    = Fib(2) + Fib(1) + Fib(2) + Fib(2) + Fib(1) + Fib(2) + Fib(1) + Fib(2);

如果要对此进行改进,我们可以缓存中间结果,然后每次从缓存结果中读取即可。
下面我们看基于尾递归的实现

实现方法3: 基于尾递归

基于尾递归在LintCode上是能通过的,在给出代码前,先介绍尾递归:
顾名思义,尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量. 直接让被调用的函数返回时越过调用者, 返回到调用者的调用者去。尾递归就是把当前的运算结果(或路径)放在参数里传给下层函数,深层函数所面对的不是越来越简单的问题,而是越来越复杂的问题,因为参数里带有前面若干步的运算路径。
下面是具体实现的代码:

public int fibonacci(int n){
    if (n == 1){
        return 0;
    }else if(n == 2)
        return 1;
    else
        return Tail(n, 0, 1, 3);
}

private int Tail(int n, int b1, int b2, int begin){
    if (n == begin){
        return b1 + b2;
    }else{
        return Tail(n, b2, b1 + b2, begin + 1);
    }
}

为了加深对代码的理解,我们用一个过程来模拟:

fibonacci(7) = Tail(7, 0, 1, 3)
     = Tail(7, 1, 2, 4)
     = Tail(7, 2, 3, 5)
     = Tail(7, 3, 5, 6)
     = 8

很容易看到,整个尾递归过程,只有不断往深,但却不用不必要往回(进行相加),故对于支持尾递归的语言,其编译器会进行优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值