这个问题简单说来是这样的:你上楼梯可以选择一次迈一个台阶,或者一次迈两个台阶,问上N级台阶,一共有几种方法。
恍惚之间让我想到我万恶的中学数学,这似乎是排列组合问题,于是我又重温了一遍组合公式。世界上一切知识都是用进废退的,哪怕我微积分学的再好,2年不用也是从头学起。幸好排列组合公式很简单,我又推导了一遍。
这问题可以这样看:通过确定迈2级台阶的数量,再排列组合他们的位置。以7级台阶为例,
0次的话,就是7步一级一级上台阶,只有1种可能;
1次的话,就是1一个2级,5个1级,共6步。就像一共有6个位置,选择一个放置迈2级台阶的元素,是C(6,1),就是从6个里面选出来1个的组合。有6种可能。
2次的话,就是2个2级,3个1级,共5步。就像一共有5个位置,选择两个放置迈2级台阶的元素,是C(5,2),就是5个里面选出来2个的组合,并且是元素之间是无序的。有10种可能。
3次的话,就是3个2级,1个1级,共4步。就像一共有4个位置,选择三个放置迈2级台阶的元素,是C(4,3),就是从4个里面选出来3个的组合。有4种可能。
4次,已经超过了7级台阶,结束。
从而,剩下的就是从0开始到最大的2级台阶出现次数,每种情况排列组合。
<span style="white-space:pre"> </span>double Fact(int n, double sum)
{
if (n <= 1)
{
return sum;
}
return Fact(n - 1, n * sum);
}
int CC(int m, int n)
{
double sum = 1;
double d1 = Fact(n, sum);
sum = 1;
double d2 = Fact(m, sum);
sum = 1;
double d3 = Fact(n - m, sum);
double d = d1 / d2 / d3;
return d + 0.5;
}
int climbStairs(int n) {
int count = n / 2;
int ret = 0;;
for (int i = 0; i <= count;i++)
{
int k = n - i * 2;
int cc = CC(i, i + k);
ret += cc;
}
return ret;
}
原来上个楼梯都有这么多学问,看来计算机最后都是数学问题,虽然实际上并没啥用。
注意计算阶乘时候,13的阶乘已经超过int型的上限,double型计算有累计误差需要纠正一下。利用前面题目积累的函数,尾递归求阶乘。这个时候,才发现这个网站题目设计的科学性,就像教材一样循序渐进,如果我大学时候能遇到这样的网站多好,哎。不过遇到也没用,那个时候我连电脑都没有,就像现在有了驾照没有车开似的,看来有些事情是不能超前的。
完成A目标有B,C条件,你要完成A,先达到了B,然后不停等C,这样并不是好办法。优化算法是,先完成困难的C,再顺利的完成B,顺理成章完成A。分步骤解决问题是人生一大课题,不要太超前。