java算法之简单的费波拉契数列Climbing Stairs

28 篇文章 0 订阅

转载自:http://blog.csdn.net/ylyg050518/article/details/48450399

爬楼梯问题是一个经典的递归斐波那契数列问题。这个问题也见于leetcode (www.leetcode.com)网站中。今天来说说它。

问题描述

原文

You are climbing a stair case. It takes n steps to reach to the top. 
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

大意:假设你正在爬楼梯,一共需要n步才能到达顶部。每次你只能爬一个台阶或者两个台阶。你有多少种爬到顶端的方式?

思路分析

当你看到这个问题的时候,你会感到这可能是一个数学问题,想了很久,却发现很难找到一个确定的数学关系来求得结果。但事实上,当你知道这是一个斐波那契数列模型的话,你就会恍然大悟。设f(n)表示爬到n阶楼梯的所有的方法。为了爬到第n阶楼梯,有两个选择,1.从第n-1阶爬一阶,或者从n-1阶向上爬两阶。因此我们可以得到f(n)与f(n-1)的对应关系:f(n)=f(n-1)+f(n-2).很明显,这是一个斐波那契数列。

特别注意:此题转化为对斐波那契数列的求法和优化问题,另外要特别注意递归的结束条件,否则会造成栈溢出而导致程序崩溃。(当递归层级很深时,无终止递归调用,就等价于无限循环调用方法,消耗了所有的栈空间,导致栈溢出,程序报StackOverflowError错误。)

方法一

/*
* 传统递归方法
*
/
    public static int ClimbStairs1(int n) {
        if (n <= 0)
            return 0;
        if (n == 1)// 递归结束条件
            return 1;
        if (n == 2)
            return 2;
        return ClimbStairs1(n - 1) + ClimbStairs1(n - 2);
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

说明:常规递归算法很容易书写,但是要注意递归的结束条件,递归算法的时间复杂度O(n),空间复杂度O(1)。

方法二

除了采用递归方法以外,我们也可以通过通过非递归的方式模拟数列的生成过程。

    /*
     * 临时变量法,模拟斐波那契数列计算过程
     */
    public static int ClimbStairs2(int n) {
        if (n <= 0)
            return 0;
        if (n == 1)
            return 1;
        int temp1 = 1, temp2 = 1, sum = 0;
        for (int i = 1; i < n; i++) {
            sum = temp1 + temp2;
            temp1 = temp2;
            temp2 = sum;
        }

        return sum;
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

说明:这种算法模拟了手工计算求解过程,时间复杂度为O(n),空间复杂度O(1)。

方法三

    /*
     * 公式法计算结果
     */
    public static int ClimbStairs3(int n) {
        double s1 = Math.sqrt(5);
        double s2 = (Math.pow((1 + s1) / 2, n + 1) + Math.pow((1 - s1) / 2,
                n + 1)) / s1 + 0.5;
        int result = (int) Math.floor(s2);
        return result;

    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

说明:公式法利用了斐波那契数列的通项公式为image,时间复杂度为O(1),空间复杂度也为O(1)。

Demo下载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值