问题描述
一共有num节台阶,一次可以上一节或者上两节,问一共有多少种走法
例如:num = 4,则有一下几种情况:
- 走四步:一次一节上
- 走三步:一次两节+两次一节
-
走两步:两次两节
故上四节楼梯一共有五种走法
思路
若问上五十节台阶有多少种走法
-
不采用 “一次上两步” 的走法
一共要走50步,每步都上一个台阶,所得结果为:
-
采用一次 “一次上两步” 的走法
一共要走49步,48步上一个台阶,1步上两个台阶,所得结果为:
-
采用两次 “一次上两步” 的走法
一共要走48步,46步上一个台阶,2步上两个台阶,所得结果为:
… … … … … …
… … … … … …
… … … … … …
-
最多采用50 / 2 = 25次 “一次上两步” 的走法
一共要走25步,每步都上两个台阶,所得结果为:
综上,把所有情况的累加就是最终答案
规律总结
通过以上分析可得出,如果总台阶数为num,则走法的数量为:
代码实现
创建一个名为Steps的类
num :总台阶数
ok :初始值为0,判断能否约分
getOptions() :获得所有走法的总数量
getUp() : 获得分母
getD() : 获得分子
关键:
因数据过大,主要要解决数据溢出问题,故想办法将数据变小,有两个方面可以减小数据
-
约分,在计算分母的getU()方法中,设定当n达到一定大小时(38行,这里定为
10), 每多乘以一个数,就判断当前值能否整除7的阶层,若可以整除(38行),
则 将ok的值设为1,并将结果除以7的阶层以达到减小数值防止溢出的作用,然后,
用ok的值为1作为判条件在getD()方法计算分子时,可直接从8开始算起(54行),
同时,为防止在getU()方法中的值在后来的计算中又出现可以整除7的阶层的数,
故用ok的值作为判断 条件,如果ok等于0,则进入,并将OK的值改为1,反过来
制约下一次碰到整除7的阶层的数导致多除(记得每循环一次后讲ok置零,第14
行和21行) -
利用排列组合的对称性可得到该公式
当不等式2b > a-b,即b>( a / 3 )成立时(第9行),可利用该公式,减小运算结果,防止数据溢出
Steps类代码
public class Steps {
int ok = 0, num;
public long getOptions(int num) { // num为总台阶数
long sum = 0, a, b;
long c;
this.num = num;
for (int n = 0; n <= (num / 2); n++) { // n为一次走两步的次数,取值范围从0到 num / 2
if (n > (num / 3)) {
a = getU(num - n, num - 2 * n);
b = getD(num - 2 * n);
c = a / b;
sum += c;
ok = 0;
continue;
}
a = getU(num - n, n);
b = getD(n);
c = a / b;
sum += c;
ok = 0;
}
return sum;
}
private long getU(int a, int n) {
long f = 1;
int start = a - n + 1;
if (n == 0 || n == a) {
return f = 1;
} else if (n == 1) {
return f = a;
}
for (int i = a; i >= start; i--) {
f = f * i;
if (n > 10 && f % 5040 == 0 && ok == 0) {
ok = 1;
f = f / 5040;
continue;
}
}
return f;
}
private long getD(int n) {
long f = 1;
if (n == 0)
return f = 1;
else if (n == 1) {
return f = 1;
} else if (ok == 1 && n >= 10) {
for (int i = 8; i <= n; i++) {
f = f * i;
}
return f;
} else {
for (int i = 2; i <= n; i++) {
f = f * i;
}
return f;
}
}
}
测试类代码
class Text {
public static void main(String[] args) {
Steps a = new Steps();
System.out.println("一共有 " + a.getOptions(50) + " 种走法");
}
}
运行结果
当台阶数为4时
当台阶数为30时
当台阶数为50时
总结
以上就是我对上台阶问题的想法,可能比递归复杂很多,但是是我自己的想法。
ps:发这篇文章主要是记录记录自己的想法,如果说的有什么不对的地方欢迎大家指正。
初次入坑,请各位大佬多多指教