算法系列--Climbing Stairs

来源:互联网 发布:skype 4.3 for ubuntu 编辑:程序博客网 时间:2024/04/30 12:16

  爬楼梯问题是一个经典的递归斐波那契数列问题。这个问题也见于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);    }

说明:常规递归算法很容易书写,但是要注意递归的结束条件,递归算法的时间复杂度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;    }

说明:这种算法模拟了手工计算求解过程,时间复杂度为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;    }

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

0 0
原创粉丝点击