LeetCode 75 —— 746. 使用最小花费爬楼梯

106 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情

LeetCode 75 —— 746. 使用最小花费爬楼梯

一、题目描述:

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

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

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

示例 1:

输入:cost = [10,15,20]

输出:15

解释:你将从下标为 1 的台阶开始。

  • 支付 15 ,向上爬两个台阶,到达楼梯顶部。 总花费为 15 。

示例 2:

输入:cost = [1,100,1,1,1,100,1,1,100,1]

输出:6

解释:你将从下标为 0 的台阶开始。

  • 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
  • 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
  • 支付 1 ,向上爬一个台阶,到达楼梯顶部。
  • 总花费为 6 。

提示:

2 <= cost.length <= 1000

0 <= cost[i] <= 999

来源:力扣(LeetCode)

链接:leetcode.cn/problems/mi…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    看到这道题目,我的第一思路因为每次只能爬一阶或者两阶,所以获取cost[i]之后cost[i+1]和cost[i+2]的值,然后比较这两个的大小,取小的路径走,这样就会出大问题:

    func minCostClimbingStairs(cost []int) int {
        c := 0
        i := 0
        for i < len(cost)-1 {
            c += cost[i]
            fmt.Println(c,i)
            if i+2 < len(cost) && i+1 < len(cost){
                if cost[i+1] < cost[i+2] {
                    i++
                }else{
                    i+=2
                }
            }else if i+2 >= len(cost) && i+1 < len(cost){
                i++
            }
           
        }
        return c
    }
    

    当输入为[10,15,20]时,会出现走10、15、20的路径。

    于是,我想到用动态规划来解决此道题。设置数组dp,其dp[i]放置的是从开始到当前下标i的最小花费。可以将下标0和1作为初始阶梯,即dp[0]和dp[1]都等于0。

    所以有状态转移方程:

    dp[i] = min(dp[i-1] + cost[i-1] , dp[i-2]+cost[i-2])

    然后按顺序计算dp中的每一项的值,最终得到dp[n]到达楼顶的最小花费。

    func minCostClimbingStairs(cost []int) int {
        n := len(cost)
        dp := make([]int, n+1)
        for i := 2; i <= n; i++ {
            if dp[i-1]+cost[i-1] < dp[i-2]+cost[i-2]{
                dp[i] = dp[i-1]+cost[i-1]
            }else {
                dp[i] = dp[i-2]+cost[i-2]
            }
        }
        return dp[n]
    }
    ​
    
  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    不是啊!!!!!

    我太菜了!!!!!

    宝宝菜菜,要抱抱!

    注意思路要对啊,大佬!!!

  3. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

    二维数组解法,还是动态规划,这道题就是典型的动态规划入门题。

    func minCostClimbingStairs(cost []int) int {
        dp := make([][]int,len(cost))
        dp[0] = []int{cost[0],cost[0]}
        dp[1] = []int{cost[0],cost[1]}
        for i := 2;i < len(cost);i++ {
            dp[i] = []int{
                dp[i-1][1],
                min(dp[i-1][0] + cost[i],dp[i-1][1] + cost[i]),
            }
        }
        return min(dp[len(cost)-1][0],dp[len(cost)-1][1])
    }
    ​
    func min(a,b int) int {
        if a > b {
            return b
        }
        return a
    }
    ​
    作者:purelightme
    链接:https://leetcode.cn/problems/min-cost-climbing-stairs/solution/dong-tai-gui-hua-er-wei-golang-yu-da-jia-neht/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

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

    func minCostClimbingStairs(cost []int) int {
        n := len(cost)
        pre, cur := 0, 0
        for i := 2; i <= n; i++ {
            pre, cur = cur, min(cur+cost[i-1], pre+cost[i-2])
        }
        return cur
    }
    ​
    func min(a, b int) int {
        if a < b {
            return a
        }
        return b
    }
    ​
    作者:LeetCode-Solution
    链接:https://leetcode.cn/problems/min-cost-climbing-stairs/solution/shi-yong-zui-xiao-hua-fei-pa-lou-ti-by-l-ncf8/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    

三、AC 代码:

func minCostClimbingStairs(cost []int) int {
    n := len(cost)
    dp := make([]int, n+1)
    for i := 2; i <= n; i++ {
        if dp[i-1]+cost[i-1] < dp[i-2]+cost[i-2]{
            dp[i] = dp[i-1]+cost[i-1]
        }else {
            dp[i] = dp[i-2]+cost[i-2]
        }
    }
    return dp[n]
}
​

四、总结:

典型的动态规划题目!可以使用滚动数组的思想,将空间复杂度优化到 O(1)。

模板来源:

作者:掘金酱

链接:juejin.cn/post/706970…

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。