https://leetcode-cn.com/problems/climbing-stairs/
一 题目
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1: 输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2: 输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
二 递归分析
这是典型的递归类问题,这类问题的核心就是数学归纳法:
当 n = 1 时,上楼梯的方式:从0阶爬1阶。
当 n = 2 时,上楼梯的方式:①从0阶(2-2)爬2阶;②从1阶(2-1)爬1阶。
当 n = 3 时,上楼梯的方式:①从1阶(3-2)爬2阶;②从2阶(3-1)爬1阶。
……
当 n = k 时,上楼梯的方式:①从k-2阶爬2阶;②从k-1阶爬1阶。
因此,要求爬上 n 阶楼梯的方式,就是求爬 n-1 阶梯的方式与爬 n-2 阶梯的方式之和。
函数就是:f(n) = f(n-1)+f(n-2)
递归方式就很显然了,递归的终结点就是 n-1 = 1 或 n-1 =2 时
三 递归解题方法-1
1. 代码
package top.black.leetcode.s0070climbStairs;
class Solution {
public int climbStairs(int n) {
return climb(n);
}
private int climb(int n){
if(n == 1){
return 1;
}else if(n == 2){
return 2;
}
return climb(n-1)+climb(n-2);
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println("1阶:"+solution.climbStairs(1));
System.out.println("2阶:"+solution.climbStairs(2));
System.out.println("3阶:"+solution.climbStairs(3));
System.out.println("4阶:"+solution.climbStairs(4));
System.out.println("5阶:"+solution.climbStairs(5));
System.out.println("6阶:"+solution.climbStairs(6));
}
}
2. 存在的问题
当 n 越大时,递归的深度会越深,因此需要进行的计算次数也越多,导致当n达到一定程度时,运行的测试用例会超出时间限制。
思考:为什么会出现这样的情况?有什么地方是我们没有想到的?
再回忆递归的过程:
f(n) = f(n-1) + f(n-2);
f(n-1) = f(n-2) + f(n-3);f (n-2) = f(n-3)+f(n-4);
f(n-3) = f(n-4)+f(n-5);f(n-4) = f(n-5)+f(n-6);
……
此时我们应该要发现,在进行递归f(n)时,f(n-1) 会计算 f(n-2) 和 f(n-3) 的结果,然后又计算了一遍 f(n-2) 的结果,然后求和。然后这样树形展开下去,会发现,整个程序计算中,存在着大量的计算重复值的过程,而这些重复计算,会浪费我们大量的内存和时间,因此,需要对这部分过程进行优化。
四 递归解题方法-2优化
我们可以将已经计算好的结果存储在一个hashmap或者数组中,只有取不到值的时候,才进行计算。
1. 代码
package top.black.leetcode.s0070climbStairs;
class Solution {
int []num ;
public int climbStairs(int n) {
num = new int[n+1];
return climb(n);
}
private int climb(int n){
if(n == 1){
return 1;
}else if(n == 2){
return 2;
}
// 1. 先从数组中取值,看是否为0
// 如果为0,则代表没计算过
// 如果不为0,则直接返回取出的值
int sum = num[n];
if(sum>0){
return sum;
}
// 计算出当前层结果
sum = climb(n-1)+climb(n-2);
// 存储到数组中
num[n] = sum;
return sum;
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println("1阶:"+solution.climbStairs(1));
System.out.println("2阶:"+solution.climbStairs(2));
System.out.println("3阶:"+solution.climbStairs(3));
System.out.println("4阶:"+solution.climbStairs(4));
System.out.println("5阶:"+solution.climbStairs(5));
System.out.println("6阶:"+solution.climbStairs(6));
}
}