LeetCode0070-爬楼梯
递归经典题目-爬楼梯
https://leetcode-cn.com/problems/climbing-stairs/
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
递归的三个条件:
1.一个问题的解可以分解为几个子问题的解
2.这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
3.存在递归终止条件。
写递归代码的关键就是找到如何将大问题分解为小问题的规律,并且基于此写 出递推公式,然后再推敲终止条件,最后将递推公式和终止条件翻译成代码。
编写递归代码的关键是,只要遇到递归,我们就把它抽象成一个递推公式,不用想一 层层的调用关系,不要试图用人脑去分解递归的每个步骤。
编写递归代码的关键就是不要把自己绕进去,正确姿势 是写出递推公式,找出终止条件,然后再翻译成递归代码。
摘自:数据结构与算法之美 王争
一、递归实现
最简单的实现方式:
class Solution { public int climbStairs(int n) { if(n==1) return 1; if(n==2) return 2; return climbStairs(n-1)+climbStairs(n-2); }
上述过程,重复计算部分消耗了最多的时间资源,导致执行时会直接超时,
下面做了重复计算的剔除,用hashmap记录每一层的结果值,如果曾经计算过,就不去重新计算,
class Solution {
//注意静态变量的使用方式 static HashMap<Integer,Integer> temp = new HashMap<Integer,Integer>();
//需要把静态变量的初始化内容放到static代码块中,否则系统会报错 static { temp.put(1,1); temp.put(2,2);} public int climbStairs(int n) { int res=0; if(temp.containsKey(n)) return temp.get(n); else{ res= climbStairs(n-1)+climbStairs(n-2); temp.put(n,res); } return res; } }
二、递归的非递归实现->动态规划
基本上所有的递归代码都可以改为迭代循环的非递归写法,因为递归本身就是接住栈来实现的。其实非递归实现模拟的是手动入栈出栈的操作,本质不变。
public int climbStairs(int n) { int p=0,q=0,r=1; for(int i=1;i<=n;i++){ p=q; q=r; r=p+q; } return r; }
动态规划与递归:
一句话,去除了重复计算的递归就是动态规划。