dp,先给前两个台阶初始化,从3跳到n。这里我们直接省略空间复杂度,因为只要记录当前台阶的前两个台阶的方法数即可,不用开数组了,容易写错的是,因为我们要将当前台阶赋给下面一个,下一个赋给下两个,顺序千万不能错,要先将下一个赋给下两个才行
class Solution {
public:
int climbStairs(int n) {
//dp即可,记录前一个台阶有几种方法能到达
if(n <= 2) return n;
int lastTwo = 1, lastOne = 2;
int res = 0;
for(int i = 3; i <= n; ++i){//从3跳到n
res = lastOne+lastTwo;
lastTwo = lastOne;
lastOne = res;
}
return res;
}
};
翻车了,如果<=2直接返回n,两个数字记录当前台阶的前两节。从第三节开始跳(是先计算第三节有几种方法),状态转移方程是前两节的方法和,记得更新前两节,前两节变为前一节,前一节变为当前。
class Solution {
public:
int climbStairs(int n) {
//dp[i]存的是第i级台阶有几种方法跳上
//初始化,dp[0] = 1,dp[1]=1
//状态转移方程,dp[i] = dp[i-1]+dp[i-2]
//因为只要记录前两个,所以不用dp数组了
if(n <= 2) return n;
int pre2 = 1, pre1 = 2;//分别是前2个和前一个
int res = 0;
//直接从3开始跳
for(int i = 3; i <= n; ++i){
res = pre1 + pre2;
pre2 = pre1;
//要的就是更新完的值
pre1 = res;
}
return res;
}
};
递归也很简单,来一个值记录当前第几级就行,更新pre的顺序别弄错
class Solution {
public:
int dfs(int pre1, int pre2,int cur, int n){
if(cur == n){
return pre1 + pre2;
}
return dfs(pre2,pre1+pre2,cur+1,n);
}
int climbStairs(int n) {
//dp含义:dp[n]记录的是爬到第n个台阶有几种方法
//转移方程:dp[n] = dp[n-1]+dp[n-2],因为n-2有一种方法跳上来,n-1也有一种方法跳上来,所以dp[n] = dp[n-1]*1 + dp[n-2]*1
//记得初始化
if(n <= 3) return n;
//压缩一下,只要记录前两节台阶就行
int pre1 = 1, pre2 = 2;
// int res = 0;
// for(int i = 3; i <= n; ++i){
// res = pre1+pre2;
// pre1 = pre2;
// pre2 = res;
// }
return dfs(pre1,pre2,3,n);
}
};
class Solution {
public:
int dfs(int pre1, int pre2, int tmp ,int n){
if(tmp == n) return pre1+pre2;
return dfs(pre2,pre1+pre2,tmp+1,n);
}
int climbStairs(int n) {
//迭代,用dp[i]记录跳上当前台阶有几种方法
//状态转移:dp[i] = dp[i-1]*1+dp[i-2]*1
//basecase:dp[1] = 1,dp[2] = 1,因为只要前两个状态可以进行状压
if(n <= 2) return n;
// int pre1 = 1, pre2 = 2;
// int res = 0;
// for(int i = 3; i <= n; ++i){
// res = pre1+pre2;
// pre1 = pre2;
// pre2 = res;
// }
// return res;
//dfs就是在内部计算每一级台阶有几种方法跳上
return dfs(1,2,3,n);
//或者自顶向下递归,用记忆化搜索,但是记忆化搜索就要线性空间复杂度了
}
};