dp刷题-爬楼梯

爬楼梯

题目描述

原题链接:70. 爬楼梯 - 力扣(LeetCode)

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:

1
2
3
4
5
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1
2. 2

示例 2:

1
2
3
4
5
6
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1
2. 1 阶 + 2
3. 2 阶 + 1

提示:

  • 1 <= n <= 45

解题思路

每次可以爬一级或者两级,因此最后一次要么是爬了1级,要么是爬了2级,所以问题可以转化为爬上(n-1)级楼梯和爬上(n-2)级楼梯分别有多少种方法,再求两者的和,即:
f(x)=f(x-1)+f(x-2);也就是斐波那契数列。

此题中,base case是:dp[0] = 0,dp[1] = 1;dp[2]=2
状态转移方程是:dp[i] = dp[i-1] + dp[i-2];

代码

状态压缩,每次只记录必要的数据,即前两个数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int climbStairs(int n) {
if(n < 3){
return n;
}
int a = 1, b = 2;
for(int i = 3; i <= n; i++){
int c = a + b;
a = b;
b = c;
}
return b;
}
}

AC记录如下:

image-20230626190019486

可以看出内存还可以优化,突然想起来两数的替换好像可以不用开辟额外的内存空间,如果我要替换a和b代码如下:

1
2
3
a=a+b;
b=a-b;
a=a-b;

在此基础上略微修改,我们需要的值是a+b最后在b上,b在a上,如此代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int climbStairs(int n) {
if(n < 3){
return n;
}
int a = 1, b = 2;
for(int i = 3; i <= n; i++){
// 计算这一轮的新值
a=a+b;
// 替换位置
a=a+b;
b=a-b;
a=a-b;
}
return b;
}
}

AC记录如下:

image-20230626191222403

可以看出还可以继续优化(剩下的0.25%是什么魔鬼><),仔细想想,for循环中的i好像可以优化掉,然后试了一下,内存反倒增加了

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int climbStairs(int n) {
if(n < 3){
return n;
}
int a = 1, b = 2;
for(;n >= 3;n--){
a=a+b;
a=a+b;
b=a-b;
a=a-b;
}
return b;
}
}

AC记录:

image-20230626192729974

内存这个东西好像要靠运气,我多交了几次发现内存有波动。

image-20230626193229910

既然这样这题就到这里吧!!!>.<


dp刷题-爬楼梯
http://example.com/2023/06/26/dp刷题-爬楼梯/
作者
子川
发布于
2023年6月26日
许可协议