非递归算法解台阶问题,倒退算法

题目:一个人登台阶,一次能登一级、二级或者三级台阶,假设有n级的台阶,请编写一个java的程序将各种的走法打印出来。

问题帖见: http://www.iteye.com/topic/786239
shkailiao给出了简单的递归算法。

night_stalker也给出了优化后的递归算法。night_stalker的算法效率高了很多,具体见 http://night-stalker.iteye.com/blog/789096

正如大家知道的,递归算法是一种很有效的思想方式,可以解决很多的问题。但性能往往不是最优的。

对于这个问题,本人想出来一个算法,不需要递归,直接循环计算,简称“倒退算法”或者“进位算法”。性能比递归算法要高1到2个数量级,当然这是去除IO输出的,毕竟IO是这里最大的瓶颈。
当n=20,一共计算121415个走法
递归算法耗时:312ms
本算法耗时:47ms
当n=25,一共计算2555757个走法
递归算法耗时:7110ms
本算法耗时:329ms

首先确定一种初始走法,以后每一种走法都是在之前的走法的基础上做细小的变化而产生。

举个例子解释一下,当n=6:
首先输出第一种走法:
1,1,1,1,1,1
将最后一步减1,最后第二步加1,输出
1,1,1,1,2
将最后一步减1,最后第二步加1,输出
1,1,1,2,1
将最后一步减1,最后第二步加1,输出
1,1,1,3
将最后一步减1,最后第二步加1,由于3-1=2需要将2分解为2个1,输出
1,1,2,1,1
将最后一步减1,最后第二步加1,输出
1,1,2,2
将最后一步减1,最后第二步加1,输出
1,1,3,1
将最后一步减1,最后第二步加1,由于3+1=4需要进位并分解为2个1,输出
1,2,1,1,1
重复以上步骤,直到第一位为4,说明运算完成。

    void printOut(String s) {
    //  System.out.print(s);
    }

    void printOut(char[] c, int len) {
    //  System.out.print(s);
    }

    static char ccc[] = {'0', '1', '2', '3'};

    private void printOne(int steps[], int len) {

        if (len > 0) {
            printOut(ccc[steps[0]]);
        }
        for (int i = 1; i < len; i++) {
            printOut(',');
            printOut(ccc[steps[i]]);
        }
        printOut("\r\n");
    }

    public void yaoyuan(int n) {

        if (n <= 0) {
                return;
        }
        // 存放所有的走法
        int steps[] = new int[n];
        // 初始化为每步走1个台阶
        for (int i = 0; i < n; i++) {
                steps[i] = 1;
        }
        // 输出第一种走法
        printOne(steps, n);

        int pre = 0;
        int last = n - 1;
        while (last > 0) {
            pre = last - 1;
            switch (steps[last]) {
            case 1: {
                steps[pre]++;
                steps[last]--;
                last--;
                break;
            }
            case 2: {
                steps[pre]++;
                steps[last] = 1;
                break;
            }
            case 3: {
                steps[pre]++;
                steps[last] = 1;
                last++;
                steps[last] = 1;
                break;
            }
            }

            // 是否需要进位
              while (pre > 0 && steps[pre] == 4) {
                steps[pre] = 1;
                pre--;
                steps[pre]++;

                last++;
                steps[last] = 1;
                last++;
                steps[last] = 1;
            }
            // 是否已经结束
              if (pre == 0 && steps[0] == 4) {
                break;
            }
            // 输出一种走法
              printOne(steps, last + 1);
        }
    }


你可能感兴趣的:(算法,Blog)