public class 走楼梯 {
// 问,上楼梯一次可以走一阶台阶或者两阶台阶,求共有几种走法
//同 小青蛙跳荷叶,一次可以跳一个荷叶的距离,也可以跳两个荷叶的距离,求共有几种跳发等类似问题
public static void main(String[] args) {
int steps = 9;
System.out.println(methodValue(steps));
System.out.println(methodRecursion(steps));
System.out.println(methodMath(steps));
}
// 效率低的递归硬数
// 个人理解,什么是计算机,顾名思义,就是用于计算的,它每秒运转的速度是人类无法比拟的
// 在不考虑空间时间效率的情况下,他硬数的结果数据是最真实的,就像是你的助手
// 按照你的要求把所有的情况都摆到你面前,然后筛选过滤,当然这是在不考虑效率的情况下
// 但是结合实际开发来说,能求得正确的结果,只要快只要准,只要节省空间时间,就用你了
// 个人认为这种做法对计算机来说未免有些善良了,因为你动用了你的脑子帮助计算机完成简化了它的部分操作
// 而它的本职就是用来计算的,它本身就是死的,你可以对它有感情但不可能让它对你有感情,至少在目前的科技面前是这样
// 可能将来随着人类科技的不断进步,更新更强的拥有超级计算能力的机器普及,我们将忽略那些近乎无差的效率
// 那时这些问题都不再是问题了吧
public static int methodRecursion(int steps) {
return chooses(steps, 0, 0);
}
private static int chooses(int steps, int step, int choose) {
if (step < steps) {
for (int j = 1; j <= 2; j++) {
choose = chooses(steps, step + j, choose);
}
} else if (step == steps) {
choose++;
}
return choose;
}
// 数学方法,与直接通过计算机求得结果不同,先进行了数学上的分析,如果说第一种的过程是一条条硬数
// 那么这个方法则是对含有几次跨越两阶台阶计算的求和,相当于简单的让程序使用了一定的数法和规律
// 经过我花费一天的时间发现,从两次两步的结果开始,任何次数的两步都为上个次数结果所有小于当前台阶数减二的两步和
// 上一种依靠计算机能力硬数,在计算上占得资源更多,在效率上更慢,因为这个方法对于情况的末端都是通过计算而来的
// 这是模拟一个较长的楼梯同时调用两个方法计时几组运算的时间对比数据
// 开始时间1628576844334--方法一硬数运行完毕1628576844338--方法二数学方法运行完毕1628576844340
// 1628577431141--1628577431145--1628577431146
// 1628577463026--1628577463029--1628577463030
// 显而易见,数学方法的速度是硬数的几倍,但是代价就是我花费了一天的白天时间研究这个问题,通过这件事我得到了一个结论
// 学习的花费是一劳永逸的。我今天花的时间让我在以后面对硬数方法时拥有绝对优势,换句话讲,不断地学习,总结
// 可以让我在面对问题时不断追求更好,靠近完美,这就是我们从小接受知识学习一切的目的,有的人可能皮了,累了
// 但是你会发现他们在新的阶段和环境当中总是能得到新的知识和,自己的道理。这个话题在此不深论了
// 草稿--10
// 1
// 9
// 7+6+5+4+3+2+1 28
// 5+4+3+2+1+4+3+2+1+3+2+1+2+1+1 35
// 3+2+1+2+1+1|+2+1+1|+1 15
// 1
// 89
public static int methodMath(int steps) {
int sum = steps;
for (int i = 2; i <= (steps - steps % 2) / 2; i++) {
sum += getValue(steps, i);
}
return sum;
}
static private int getValue(int steps, int times) {
int value = 0;
for (int i = times - 1, j = steps - 2; j >= 2 * i; j--) {
if (i > 1) {
value += getValue(j, i);
} else {
value += j - 1;
}
}
return value;
}
// 逆向思维,与动态规划思维一致
// 假设有五个台阶,一次到达五阶有且只有两种情况,一是我们从3出发跨两阶,二是我们从四出发跨一阶
// 以此类推则可推出有几次到达二阶和几次到达一阶的情况,二阶两个一步或一个两步,一阶一个一步
// 就能得出一个关于阶数与一阶次数,二阶次数的正比例函数,这也体现了数学对实际问题的重要性,对算法开发优化的绝对性
// 每个数项等于它前两个数项的和,这便是斐波那契数列,听说最早是一个法国数学家解出来的
// 要不是根号平方啥的涉及到很多计算机转换问题懒得动,我早就,拿来把你了!在此对较小数字范围演示,模拟波非那切数列加以计算
// 快速,高效,效率上完胜前两种方法,如果要更快,那就模拟一个波非那切解法公式,效率更高,这几天我就尝试一下
static public int methodValue(int steps) {
long[] Fibonacci = new long[steps];
Fibonacci[0] = 0;
Fibonacci[1] = 1;
for (int i = 2; i < Fibonacci.length; i++) {
Fibonacci[i] = Fibonacci[i - 1] + Fibonacci[i - 2];
}
return (int) (Fibonacci[steps - 1] * 2 + Fibonacci[steps - 2]);
}
// 以上为解决上楼梯没事干喜欢两阶两阶走的人的情况的问题的三种思路和方法,供参考
// 全部是自己花时间的结果,写完后还查阅了对于该问题相关的资料,进行了几个地方的修改 //如有建议和想法请私信
}