爬楼梯_70_746

LeetCode_70原题链接:https://leetcode-cn.com/problems/climbing-stairs/

题目描述:

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

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

复制代码
动态规划:
1.本问题可以分成多个子问题,爬第n阶楼梯的方法数量,等于 2 部分之和。
2.爬上 n−1 阶楼梯的方法数量。因为再爬1阶就能到第n阶
3.爬上 n−2 阶楼梯的方法数量,因为再爬2阶就能到第n阶
4.所以我们得到公式 dp[n] = dp[n-1] + dp[n-2]
  同时需要初始化 dp[0]=1 和 dp[1]=1
  时间复杂度:O(n)

其中dp[n],表示爬上该楼梯的可能性。
dp[0],爬上0层,可能走法初始为1种
dp[1], 爬上1层,可能走法为1种
dp[2], 爬上2层,则可能的走法为2种,dp[0]+dp[1].
dp[3], 爬上3层,则可能的走法有dp[2]+dp[1]加起来。

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];
    }
}

class Solution {
    public int climbStairs(int n) {
        int[] memo = new int[n+1];
        return climbStairsMemo(n, memo);
    }
    public int climbStairsMemo(int n, int[] memo) {
        if(memo[n] > 0) {
            return memo[n];
        }
        if(n == 1) {
            memo[n] = 1;
        } else if (n == 2) {
            memo[n] = 2;
        } else {
            memo[n] = climbStairsMemo(n-1, memo) + climbStairsMemo(n-2, memo);
        }
        return memo[n];
    }
}
复制代码

跳台阶扩展问题:https://www.nowcoder.com/practice/22243d016f6b47f2a6928b4313c85387

题目描述:

  一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶(n为正整数)总共有多少种跳法。

复制代码
1.当n = n时,Fiber(n)= Fib(n-1) + Fib(n-2) + ....Fib(0);
2.当n = n-1时,Fiber(n-1)=  Fib(n-2) + Fib(n-3)......Fib(0);
两者相减,Fiber(n)= 2 * Fiber(n-1);

public class Solution {
    public int JumpFloorII(int target) {
        if(target <= 1){
            return 1;
        }
        return 2 * JumpFloorII(target-1);
    }

    public int jumpFloorII(int target) {
        if(target < 2) {
            return 1;
        }
        return (int) Math.pow(2,target-1);
    }

    public int jumpFloorII(int target) {
        if(target==0 || target==1) {
            return 1;
        }
        int a = 1, b = 0;
        for (int i=2; i<=target; i++){
            b = a<<1;
            a = b;
        }
        return b;
    }
}
复制代码

LeetCode_746原题链接:https://leetcode-cn.com/problems/min-cost-climbing-stairs/

题目描述:

  给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

  你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

  请你计算并返回达到楼梯顶部的最低花费。

复制代码
动态规划:
1.假设数组 cost 的长度为 n,
  则 n 个阶梯分别对应下标 0 到 n−1,楼层顶部对应下标 n,问题等价于计算达到下标n 的最小花费。
2.创建长度为 n+1 的数组 dp,其中 dp[i] 表示达到下标 i 的最小花费。
3.由于可以选择下标 0 或 1 作为初始阶梯,因此有 dp[0] = dp[1] = 04.当 2≤i≤n 时,
    可以从下标 i−1 使用 cost[i−1] 的花费达到下标 i,
    或者从下标 i−2 使用 cost[i−2] 的花费达到下标 i。
5.为了使总花费最小,dp[i] 应取上述两项的最小值,
    因此状态转移方程如下:
    dp[i]=min(dp[i−1]+cost[i−1], dp[i−2]+cost[i−2])
6.依次计算 dp 中的每一项的值,最终得到的 dp[n] 即为达到楼层顶部的最小花费。

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int[] dp = new int[n + 1];
        dp[0] = dp[1] = 0;
        for (int i = 2; i <= n; i++) {
            dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        }
        return dp[n];
    }
}

上述代码的时间复杂度和空间复杂度都是 O(n)。
注意到当 i≥2 时,dp[i] 只和 dp[i−1] 与 dp[i−2] 有关,
因此可以使用滚动数组的思想,将空间复杂度优化到 O(1)。

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int prev = 0, curr = 0;
        for (int i = 2; i <= n; i++) {
            int next = Math.min(curr + cost[i - 1], prev + cost[i - 2]);
            prev = curr;
            curr = next;
        }
        return curr;
    }
}

时间复杂度:O(n),其中 n 是数组 cost 的长度。
需要依次计算每个 }dp 值,每个值的计算需要常数时间,因此总时间复杂度是 )O(n)。
空间复杂度:O(1)。使用滚动数组的思想,只需要使用有限的额外空间。
复制代码

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------恢复内容结束------------

posted @   2022年总冠军gogogo  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示