【Leetcode】746. Min Cost Climbing Stairs

da【Leetcode】746. Min Cost Climbing Stairs
开始重温dp法, 要秋招了,很菜很慌
爬楼梯,踩在某个台阶上就要支付对应的钱,求需要最少钱爬到楼顶。(注意这里楼顶不是数组的最后一个元素,而是最后一个元素的下一个)

方法1 DP法

每次当前楼梯可以由上一个楼梯或者上上个楼梯爬来,很容易写出递推方程dp[i] = min(dp[i-1], dp[i-2]) + cost[i],注意起始条件和楼顶条件即可,楼顶可令cost = 0,如果不求楼顶的dp,可以求倒数两个楼梯dp的最小值

class Solution(object):
    def minCostClimbingStairs(self, cost):
        """
        :type cost: List[int]
        :rtype: int
        """
        cost.append(0)
        dp = [0 for i in range(len(cost))]
        for i in range(len(cost)):
            if i <= 1:
                dp[i] = cost[i]
            dp[i] = min(dp[i-1], dp[i-2]) + cost[i]
        return dp[-1]

方法2 递归

DP法一般都可以写成递归的形式,最直接的改写如下

class Solution(object):
    def minCostClimbingStairs(self, cost):
        """
        :type cost: List[int]
        :rtype: int
        """
        cost.append(0)
        return self.helper(cost,len(cost)-1)
        
    def helper(self, cost, N):
        if N <= 1:
            return cost[N]
        else:
            return min(self.helper(cost, N-1), self.helper(cost, N-2)) + cost[N]   

但这样写的坏处就是有很多重复的计算,可以用字典保存已经计算过的元素,改进版如下

class Solution:
    def minCostClimbingStairs(self, cost):
        """
        :type cost: List[int]
        :rtype: int
        """
        self.dict = {0: cost[0], 1: cost[1]}
        cost.append(0)
        return self.helper(len(cost)-1,cost)

    def helper(self, N, cost):
        if N in self.dict:
            return self.dict[N]
        else:
            self.dict[N] = min(self.helper(N-1, cost), self.helper(N-2, cost)) + cost[N]
            return self.dict[N]

方法3 改进的DP

方法1 中的dp需要O(n)的存储变量,但实际我们只需要两个变量来存储到当前楼梯前1楼梯的消耗即可

class Solution2:
    def minCostClimbingStairs(self, cost):
        """
        :type cost: List[int]
        :rtype: int
        """
        var,var1  = 0,0
        for c in cost:
            var1, var = var, min(var1,var) + c
        return min(var1, var)