楼梯算法 -- 重在思想
前一段时间遇到了一个算法题,印象非常深刻,题目也很简单:
一个人上楼梯,可以一次跨一阶楼梯,也可以一次跨两阶,但是最多一次跨三阶楼梯,请问,在 n 层楼梯的条件下,一个人上楼梯总共有几种方式?
举个例子: 比方说有 1 层楼梯,一个人只能跨一阶上去,也就是只有 1 种上楼梯的方法;
若有 2 层楼梯,那么可以一阶一阶地上,也可以一次跨两阶,也就是有 2 种上楼梯的方法;
若有 3 层楼梯,那么可以一阶一阶地上,也可以先跨两阶+后跨一阶,同样也能先跨一阶+后跨两阶,还可以一次跨三阶,也就是有 4 种上楼梯的方法;
。。。
那么如果有 n 层,那有几种上方呢??(附加:可以都列出来吗?)
思路:对于 n 层楼梯,分为三种情况:
1> 第一脚跨了一阶楼梯,那么就有 F(n - 1) 种上法(F 作为这个未知函数,返回 n 层楼梯有几种上法);
2> 第一脚跨了两阶楼梯,那么就有 F(n - 2) 种上法;
3> 第一脚跨了三阶楼梯,那么就有 F(n - 3) 种上法。
故:F(n) = F(n - 1) + F(n - 2) + F(n - 3)
有了这个关系,相信写出一个递归地求几种上法的函数就不难了吧?
关键是:怎样把它们都列出来呢?
我试着用 JS 小小地实现了一下,效率不太高,仅供参考下,期待更好的答案。^ ^
(function(n){ var t = []; if(n < 4) return n == 1 ? [1] : (n ==2 ? [11, 2] : [111, 12, 21, 3]); t[n] = []; for(var i = 1; i < 4; i ++){ for(var j = 0, len = arguments.callee(n - i).length; j < len; j ++){ t[n].push(String(i) + arguments.callee(n - i)[j]); } } return t[n]; })(6);
运行结果:
["111111", "11112", "11121", "1113", "11211", "1122", "1131", "12111", "1212", "1221", "123", "1311", "132", "21111", "2112", "2121", "213", "2211", "222", "231", "3111", "312", "321", "33"]