经典问题
- 问题一:有一只青蛙上楼梯,它一次能跳一阶或者两阶楼梯,青蛙从第一层开始,问:到第N层共有多少种跳法?
- 问题二:我们玩大富翁游戏,通过摇骰子前进,骰子有六个面,分别对应1~6,摇到几就前进几步,假如从第一步开始,问:到第N步共有多少种走法?
讨论一
-
思路
- 通过逆推的思维,首先青蛙要上第N层,有两种方法:一是从第N-1层跳一步上去;二是从第N-2层跳两步上去。所以青蛙要到第N层,是到第N-1层的跳法数加上到第N-2层的跳法数,再通过以上方法分别再计算到第N-1层和第N-2层的跳法数,以此类推。
- 并且很容易得出到第二层跳法数为1,到第三层跳法数为2。
-
通过数学的方法来求解得到递推公式
- 设到第n层的跳法数为f(n)。
- 通过以上思路f(n)=f(n-1)+f(n-2),n>3且n为整数。
- f(2)=1,f(3)=2。
-
再通过递归代码实现
int fn(int n) { if(n==2) return 1; else if(n==3) return 2; else return fn(n-1)+fn(n-2); }
讨论二
-
思路
- 可采用刚刚同样的思维方式来解决,只是可能相加项多了几个
- 可以通过观察简化我们递推,如下
-
数学的方法
- 首先设到第N步走法数为f(n)。
- f(n)=f(n-1)+f(n-2)+…+f(n-5)+f(n-6),n>7且n为整数。
- 设f(1)=1,表示可以直接到达,例如f(3),除了从f(2)到达以外,还能从第一步直接到达第三步,需要加上f(1)。
- f(1)=1,f(2)=f(1)=1,f(3)=f(2)+f(1)=2,f(4)=f(3)+f(2)+f(1)=4,…,f(7)=f(6)+f(5)+f(4)+f(3)+f(2)+f(1)=32。
-
简化
- n>7时,不妨多写几个
f(n)=f(n-1)+f(n-2)+…+f(n-5)+f(n-6)
f(n-1)=f(n-2)+f(n-3)+…+f(n-6)+f(n-7)
f(n-2)=f(n-3)+f(n-4)+…+f(n-7)+f(n-8)
…
可以发现
f(n)=2fn(n-1)-f(n-7)。 - 同样在n<=7时,很容易发现
f(n)=2f(n-1) n>2,n为整数。
f(2)=1。
甚至能很轻易写出通项公式:f(n)=2(n-2) n>1,n为整数。
- n>7时,不妨多写几个
-
再通过递归实现代码
int fn(int n) { if(n==1||n==2) { return 1; } else if(n>2&&n<=7) { return 2*fn(n-1); } else { return 2*fn(n-1)-fn(n-7); } }
总结
采用以上的方法和思路可以解决斐波拉契序列及相关的问题,再通过自己的观察和化简,可以优化我们算法,甚至可以通过计算出通项公式直接去掉递归。