跳台阶

跳台阶

http://www.nowcoder.com/questionTerminal/8c82a5b80378478f9484d87d1c5f12a4

#描述 此题和斐波拉契数列做法一样。也将用三个方法来解决,从入门到会做。 考察知识:递归,记忆化搜索,动态规划和动态规划的空间优化。 难度:一星

#题解 ###方法一:递归 题目分析,假设f[i]表示在第i个台阶上可能的方法数。逆向思维。如果我从第n个台阶进行下台阶,下一步有2中可能,一种走到第n-1个台阶,一种是走到第n-2个台阶。所以f[n] = f[n-1] + f[n-2]. 那么初始条件了,f[0] = f[1] = 1。 所以就变成了:f[n] = f[n-1] + f[n-2], 初始值f[0]=1, f[1]=1,目标求f[n] 看到公式很亲切,代码秒秒钟写完。

class Solution {
public:
    int jumpFloor(int number) {
        if (number<=1) return 1;
        return jumpFloor(number-1)+jumpFloor(number-2);
    }
};

优点,代码简单好写,缺点:慢,会超时 时间复杂度:O(2^n) 空间复杂度:递归栈的空间 ###方法二:记忆化搜索 拿求f[5] 举例

通过图会发现,方法一中,存在很多重复计算,因为为了改进,就把计算过的保存下来。 那么用什么保存呢?一般会想到map, 但是此处不用牛刀,此处用数组就好了。

class Solution {
public:
    int f[50]{0};
    int jumpFloor(int number) {
        if (number <= 1) return 1;
        if (f[number] > 0) return f[number];
        return f[number] = (jumpFloor(number-1)+jumpFloor(number-2));
    }
};

时间复杂度:O(n), 没有重复的计算 空间复杂度:O(n)和递归栈的空间

方法三:动态规划

虽然方法二可以解决此题了,但是如果想让空间继续优化,那就用动态规划,优化掉递归栈空间。 方法二是从上往下递归的然后再从下往上回溯的,最后回溯的时候来合并子树从而求得答案。 那么动态规划不同的是,不用递归的过程,直接从子树求得答案。过程是从下往上。

class Solution {
public:
    int dp[50]{0};
    int jumpFloor(int number) {
        dp[0] = 1, dp[1] =1;
        for (int i = 2 ; i <= number ; i ++) dp[i] = dp[i-1]+dp[i-2];
        return dp[number];
    }
};

时间复杂度:O(n) 空间复杂度:O(n) ###继续优化 发现计算f[5]的时候只用到了f[4]和f[3], 没有用到f[2]...f[0],所以保存f[2]..f[0]是浪费了空间。 只需要用3个变量即可。

class Solution {
public:
    int jumpFloor(int number) {
        int a = 1 , b = 1 , c = 1;
        for (int i = 2 ; i <= number ; i ++) {
            c = a+b , a = b , b = c;
        }
        return c;
    }
};

时间复杂度:O(n) 空间复杂度:O(1) 完美!

全部评论
方法2需要改的地方:return dp[n]=fin(n-1,dp)+fin(n-2,dp);vector<int>dp(number,-1);</int>
1
送花
回复
分享
发布于 2021-05-31 23:08
动态规划的那个方法,初始条件应该是dp[1]=1,dp[2]=2,不应该存在0这一个初始条件,因为0阶台阶没有意义。
5
送花
回复
分享
发布于 2021-05-18 14:03
秋招专场
校招火热招聘中
官网直投
题解二 讲记忆搜索法的Fib部分递归时,也需要把vetor的地址传下去,应该写: return dp[n] = Fib(n-1, dp) + Fib(n-2, dp);
4
送花
回复
分享
发布于 2020-10-10 16:18
我改了,但是用例没通过啊
2
送花
回复
分享
发布于 2021-03-14 21:12
dp[0]为什么等于1?0个台阶不应该是0么
2
送花
回复
分享
发布于 2021-05-21 14:42
啊!!!我压根就没想过可以逆着来。
2
送花
回复
分享
发布于 2021-08-22 22:35
其实只要两个变量就可以了 int a = 1, c = 3; for (int i = 1; i < target; i++) { a = c - a; c = c + a; } return a;
2
送花
回复
分享
发布于 2022-03-09 08:46
第一种方法好像没有考虑台阶为0的情况,因此有点问题吧 class Solution: def jumpFloor(self , number: int) -> int: # write code here if number==1: return 1 if number==0: return 0 return self.jumpFloor(number-1)+self.jumpFloor(number-2)
1
送花
回复
分享
发布于 2021-11-03 21:24
dp[2]也要单独列出来的,dp[2]=2
点赞
送花
回复
分享
发布于 2021-03-15 21:01
当n=2时,这些方法计算出来的结果都是错误的。
点赞
送花
回复
分享
发布于 2021-05-18 14:05
这个记忆化搜索会在leecode报错,
点赞
送花
回复
分享
发布于 2021-06-28 22:13
最好用动态规划或者矩阵快速幂
点赞
送花
回复
分享
发布于 2021-06-28 22:15
方法3还可以省去一个变量的
点赞
送花
回复
分享
发布于 2021-08-15 13:38
第二和第三种方法都没看懂
点赞
送花
回复
分享
发布于 2021-09-08 10:23
这个逆向理解绝了
点赞
送花
回复
分享
发布于 2022-01-06 17:10
int f[50]{0};这个编码格式有什么渊源吗,第一次见,而且编译器也不认,我只能用int[] f = new int[50];代替,有没有大佬给指点一下
点赞
送花
回复
分享
发布于 2022-07-21 19:39
c++
点赞
送花
回复
分享
发布于 2022-08-31 20:07 上海
动态规划的那个错了
点赞
送花
回复
分享
发布于 2023-06-15 15:12 江西

相关推荐

308 41 评论
分享
牛客网
牛客企业服务