问题:

  从楼上走到楼下有n个台阶,每一步有3中走法:走1个台阶,走2个台阶,走3个台阶。

  如:

    当有1个台阶时,有1种走法

    当有2个台阶时,有2种走法

    当有3个台阶时,有4钟走法

  求:

    当有4个台阶时,有几种走法?

    当有5个台阶时,有几种走法?

    当有100个台阶时,有几种走法?

    请设计程序计算,对于给定的n个台阶,有几种走法?

解答思路

  1.想到类似斐波那契数列算法,得出F(n)=F(n-1)+F(n-2)+F(n-3),采用递归的办法实现,如下面calucate1方法可实现。

    但有个问题是随着楼梯台阶增多,计算量会成指数增长,时间复杂度会大大增加。

  2.采用excel计算的思路,在excel中,重上往下先定义4个值,如

    a1=1,a2=2,a3=4,a4=7,选中a2,a3,a4,采用公式F(n)=F(n-1)+F(n-2)+F(n-3)的形式,计算a5到a100的值

    如下面calucate2方法可实现。

    这样实现不太好,数组有可能太长

  3.采用定长数组,循环替换的方式,参考calucate3方法可实现。

    还有一个问题,当n=100时,数值会很大,在java中涉及到大数计算

  4.采用BigInteger,参考calucate4方法可实现。

备注:
  先分享我对这个问题的思考,抛砖引玉,欢迎大家讨论,里面还有什么问题,还可以怎么优化

import java.math.BigInteger;

public class Stair {

    public static int calucate1(int i){
        if(i<=0){
            return 0;
        }
        switch (i){
            case 1:
                return 1;
            case 2:
                return 2;
            case 3:
                return 4;
            default:
                return calucate1(i-1)+calucate1(i-2)+calucate1(i-3);
        }
    }

    public static int calucate2(int i){
        if(i<=0){
            return 0;
        }
        switch (i){
            //第1个台阶
            case 1:
                return 1;
            //第2个台阶
            case 2:
                return 2;
            //第3个台阶
            case 3:
                return 4;
            //第i个台阶
            default:
                int[] data=new int[i];
                data[0]=1;
                data[1]=2;
                data[2]=4;
                for(int j=4;j<=i;j++){
                    //计算第j个台阶时有多少种走法
                    data[j-1]=data[j-2]+data[j-3]+data[j-4];
                }
                //返回第i个台阶时有多少种走法
                return data[i-1];
        }
    }

    public static int calucate3(int i){
        if(i<=0){
            return 0;
        }
        switch (i){
            //第1个台阶
            case 1:
                return 1;
            //第2个台阶
            case 2:
                return 2;
            //第3个台阶
            case 3:
                return 4;
            //第i个台阶
            default:
                //初始化第一个,第二个,第三个台阶时的走法
                int[] data={1,2,4};
                for(int j=4;j<=i;j++){
                    //定义数组下标值
                    int index= (j-1)%3;
                    //计算数值
                    int temp=data[0]+data[1]+data[2];
                    //替换目标下标值所在位置的数值
                    data[index]=temp;
                }
                return data[(i-1)%3];
        }
    }

    public static BigInteger calucate4(int i){
        if(i<=0){
            return new BigInteger("0");
        }
        switch (i){
            //第1个台阶
            case 1:
                return new BigInteger("1");
            //第2个台阶
            case 2:
                return new BigInteger("2");
            //第3个台阶
            case 3:
                return new BigInteger("4");
            //第i个台阶
            default:
                //初始化第一个,第二个,第三个台阶时的走法
                BigInteger[] data={new BigInteger("1"),new BigInteger("2"),new BigInteger("4")};
                for(int j=4;j<=i;j++){
                    //定义数组下标值
                    int index= (j-1)%3;
                    //计算数值
                    BigInteger temp=data[0].add(data[1]).add(data[2]);
                    //替换目标下标值所在位置的数值
                    data[index]=temp;
                }
                return data[(i-1)%3];
        }
    }

    public static void main(String[] args) {
        System.out.println("---------------------1------------------------");
        //采用递归的思路
        System.out.println(calucate1(4));  //7
        System.out.println(calucate1(5));  //13
        System.out.println(calucate1(19));  //66012
//        System.out.println(calucate1(100));  //递归层级计算次数太多,代码执行起来时间复杂度巨大
        System.out.println("---------------------2------------------------");
        //excel从上往下拖动的思路
        System.out.println(calucate2(4));  //7
        System.out.println(calucate2(5));  //13
        System.out.println(calucate2(19));  //66012
        System.out.println(calucate2(100));  //随着台阶数量增长,数组长度也增长,浪费空间
        System.out.println("---------------------3------------------------");
        //采用数组值交替计算的思路
        System.out.println(calucate3(4));  //7
        System.out.println(calucate3(5));  //13
        System.out.println(calucate3(19));  //66012
        System.out.println(calucate3(100));  //可以计算值
        //解决大数值计算的问题
        System.out.println("---------------------4------------------------");
        System.out.println(calucate4(4));  //7
        System.out.println(calucate4(5));  //13
        System.out.println(calucate4(11));  //66012
        System.out.println(calucate4(1000));  //可以计算值
    }

}