问题描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
这是一道典型的递归求解问题(当然也有其它方法)
什么问题满足递归求解:三个条件
- 一个问题的解可以分解为多个子问题的解
- 子问题除了数据规模不同求解思路相同
- 递归存在终止条件
以该问题为例,青蛙每次可以跳1阶或2阶,跳完之后又是跳1阶或2阶............
可以看出青蛙的总跳法是由跳1阶或2阶的跳法决定的
设总跳法为f(n),n为阶数 先跳1阶的跳法f(n-1),加上先跳2阶的跳法f(n-2)
公式表示为 f(n) = f(n-1)+f(f-2)
存在终止条件为,显然0阶无跳法,1阶1跳法,2阶2跳法(两次1阶或1次两阶)
公式表示为 f(1) = 1;f(2)=2;
有了思路再写代码,实现如下:
import java.util.HashMap;
public class Solution {
HashMap<Integer,Integer> hashmap = new HashMap<>();
public int jumpFloor(int target) {
if(target==1)
return 1;
if(target==2)
return 2;
if(hashmap.containsKey(target))
{
return hashmap.get(target);
}
int ret = jumpFloor(target-1)+jumpFloor(target-2);
hashmap.put(target,ret);
return ret;
}
}
这里我们用了一个hashmap来存储键值对,也就是n阶台阶的跳法有几种
因为我们发现存在重复计算,如图
当我们对f(n-1)进行递归时,左边红线部分被依次计算然后被存入hashmap中,接着左边从f(n-3)开始,由于hashmap中已经有相应的键值,那么直接返回,不做计算
总结:首先是递归使用的条件,然后是它的缺点是不易理解,可能存在堆栈溢出,导致的空间复杂度高,函数调用耗时多,因为每一次调用都要保存当前的变量,也可能发生无限递归问题,比如测试条件下A->B->C->A的无限套娃
好处是高效,简洁,代码量少
编写递归代码的要点是:先写出递归公式然后找出终止条件,再转化为代码,自己不要被绕进去,人不适合处理无限套娃的思维,这是机器的强项,我们只需要注重这一层与下一层的两层关系(比如处理父子之间的关系,而屏蔽儿子和孙子的关系),屏蔽下一层、下下层,因为他们的关系一定是相同的