问题描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
这里讨论用动态规划的方式去解决问题可以达到O(n),因为暴力递归的方式存在大量重复的计算。啊?为什么存在重复的计算?我把这个问题的图解放到最后面。
1.
首先用一个场景举例: 用A B C表示三个路口 t1 t2 t3 t4表示目的地,如图。
对于C路口来说,它可达t3、t4这个两个目的地。
对于B路口来说,它可达t1、t2这两个目的地。
对于A路口来说,它可达B、C这两个路口点。
即对A路口来说,要到达目的地,需要选择去B或者C路口后,再选择t1、t2\t3、t4 其中一个路口。
所以对A路口来说,是依赖B、C路口.
B路口有两种选择,C路口有两种选择。
A可以到达B、C两个路口,则A可以有2+2种选择
2.
再看题目,回跳台阶问题,其实台阶也像上面的路口选择一样,同样是每个台阶下一步会有两种选择方案。跳一步或者两步。
这里我举一个简单的4阶的楼梯做例子。
求:在第一个台阶时,有几种方式跳到台阶4。
在台阶1有两种方式,一种是跳到2上面,一种是跳到3上面。
这意味着台阶1的选择依赖于台阶2和台阶3的选择。
即台阶1 = 台阶2的选择方式+台阶三的选择方式
让我们再看看台阶2:
台阶2的两种选择,
第一种是到达了台阶4,即到达了最终目的地。
第二种是到达了台阶3,即依赖于台阶3.
即台阶2的选择方式 = 1+台阶3的选择方式
再看看台阶3:
台阶三的话很显然只有一种选择方式了,
即台阶3的选择方式=1
由此可以推出:
台阶3的选择方式=1
台阶2的选择方式 = 1+台阶3的选择方式 = 1+1 = 2
台阶1 = 台阶2的选择方式+台阶三的选择方式 = 2+1=3种
不难发现我们从台阶3的跳法一直推到了台阶1共有几种跳法。
这里举例子是用4阶的,其实抽象出来就是,
第K阶的跳法 = 第K+1阶的跳法+第K+2阶的跳法。
下面是java实现的代码:
public int JumpFloor(int target) { //target值代表第N阶
Map<Integer,Integer> map = new HashMap<>(); //用来缓存第K阶的跳法
map.put(target,1);
int i = target-1;
while(i!=-1){
int c1 = i+1; //跳一步
int c2 = i+2; //跳两步
int count = 0;
if(c1<=target){ //未超出目标台阶
count += map.get(c1);
}
if(c2<=target){ //未超出目标台阶
count+=map.get(c2);
}
map.put(i,count);
i--; //往下走,求下一台阶的跳法。
}
return map.get(0);
}
-----------------------------------------------------------------------------手动分割--------------------------------------------------------------------------------
下面画一个粗糙的图来说一下为什么暴力递归存在大量重复计算过程:
用暴力递归的话过程大致如图所示。
不难发现出现了很多重复的值,即重复计算多次第K阶的跳法。
最后:第一次做图文,做得不太好。也发现真的不是很容易。真是感谢在博客分享知识的各位大佬们的辛勤付出。