题目
中文
https://leetcode-cn.com/problems/climbing-stairs/
英文
https://leetcode.com/problems/climbing-stairs/
You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
题解
第一遍
思路
第n阶f(n)的走法是由前面的走法加1步/2步推导来的。
1步的话则对应之前的f(n-1)
2步则对应之前的f(n-2)
以此递归。
n对应的是斐波那契数列的通项。
楼梯数 1 2 3 4
对应通项 1 1 2 3
所以如何解决斐波那契数列
1 递归绝对没问题
2 查斐波那契通项公式强行算。
int climbStairs(int n){if (n == 0)return 0;if (n == 1)return 1;else if (n == 2)return 2;elsereturn climbStairs(n - 1) + climbStairs(n - 2);}
O(2^n)
失败 超时了
所以简单点通项公式来一个
查他人题解发现这是动态规划 典型题。
本问题其实常规解法可以分成多个子问题,爬第n阶楼梯的方法数量,等于 2 部分之和
- 爬上 n-1阶楼梯的方法数量。因为再爬1阶就能到第n阶
- 爬上 n-2 阶楼梯的方法数量,因为再爬2阶就能到第n阶
所以我们得到公式 dp[n] = dp[n-1] + dp[n-2]
同时需要初始化 dp[0]=1 和 dp[1]=1
时间复杂度:O(n)O
class Solution {public int climbStairs(int n) {int[] dp = new int[n + 1];dp[0] = 1;dp[1] = 1;for(int i = 2; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}}
解法1 循环递推 非递归 保留之前值
int climbStairs(int n){if (n == 1)return 1;int n1 = 1;int n2 = 2;int temp;for (int i = 3; i <= n; i++){temp = n2;n2 = n1 + n2;n1=temp;}return n2;}
O(n)
n2=n1+n2;
所以要用一个数记住之前的n2; 即上一次的n2 这一次的n1.
一个更好理解的版本
public int climbStairs(int n) {// base casesif(n <= 0) return 0;if(n == 1) return 1;if(n == 2) return 2;int one_step_before = 2;int two_steps_before = 1;int all_ways = 0;for(int i=2; i<n; i++){all_ways = one_step_before + two_steps_before;two_steps_before = one_step_before;one_step_before = all_ways;}return all_ways;}
