代码随想录算法训练营第四十一天(动态规划篇)|理论基础,509. 斐波那契数, 70. 爬楼梯, 746. 使用最小花费爬楼梯

动态规划理论基础

动态规划:每一个状态一定是由上一个状态推导出来的。

贪心:局部直接选最优的

解题步骤

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

509. 斐波那契数

题目链接:509. 斐波那契数 - 力扣(LeetCode)

思路

  1. dp[i]的定义为:第i个数的斐波那契数值是dp[i]。
  2. 递推公式: 题目已经给出 dp[n] = dp[n-1] + dp[n-2]。
  3. dp[0] = 0, dp[1] = 1。
  4. dp[n]是依赖dp[n-1]和dp[n-2]的,所以应从前往后遍历。
  5. n从0到10的斐波那契值:0 1 1 2 3 5 8 13 21 34 55

代码实现

class Solution(object):
    def fib(self, n):
        if n <= 1:
            return n
        dp = [0, 1]
        for i in range(n):
            total = dp[0] + dp[1]
            dp[0] = dp[1]
            dp[1] = total
        return dp[0]

在for循环中,我用了range(n), 而代码随想录里是range(2, n+1), 在这个循环中,不直接用到i,只是表明循环的次数,所以可以不一样。我相当于让它循环了n次,所以最终取dp数组中第一个数,而代码随想录循环了n-1次,最终取数组中第二个数。

也可用递归法求解

class Solution(object):
    def fib(self, n):
        if n <= 1:
            return n
        return self.fib(n-1) + self.fib(n-2)

70. 爬楼梯

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

思路

到三层可以从二层爬一个阶梯,也可以从一层爬两个阶梯,因此到当前层的方法到第三层楼梯的状态可以由第二层楼梯 和 到第一层楼梯状态推导出来。

  1. dp[i]: 到达i层总共有dp[i]种方法。
  2. 可以用dp[i-2]种方法到达i-2层,再爬两层到达i层,也可以用dp[i-1]种方法到达i-1层,再爬一层到达i层,因此到达i层的方法数为到前一层和前两层的方法之和。dp[i] = dp[i-2] + dp[i-1].
  3. i为1时无意义,不考虑。dp[1] = 1, dp[2] = 2
  4. dp[i]依赖dp[i-2] 和 dp[i-1]的值,所以从前往后遍历。
  5. i为1-5:dp[i]为 1 2 3 5 8

代码实现

class Solution(object):
    def climbStairs(self, n):
        if n <= 2:
            return n
        dp = [1, 2]
        for i in range(3,n+1):
            total = dp[0] + dp[1]
            dp[0] = dp[1]
            dp[1] = total
        return dp[1]

for循环用range(3, n+1)比较清楚,表明i要从3开始计算,一直到n为止。

746. 使用最小花费爬楼梯

题目链接:746. 使用最小花费爬楼梯 - 力扣(LeetCode)

思路

  1. dp[i]: 到达i层花的最小力气。
  2. 可以花dp[i-2]到达i-2层,再花费cost[i-2]到达i层,也可以花dp[i-1]到达i-1层,再花费cost[i-1]到达i-2层,那么到达i层的最小花费就是这两种方法的花费最小的力气,即dp[i] = min(dp[i-2] + cost[i-2], dp[i-1] + cost[i-1])
  3. 到达0层和1层的花费为0, dp[0] = dp[1] = 0.
  4. 从前向后遍历。
  5. 跟据cost数据具体分析。

代码实现

class Solution(object):
    def minCostClimbingStairs(self, cost):
        if len(cost) <= 1:
            return 0
        dp = [0, 0]
        for i in range(2, len(cost)+1):
            minCost = min(dp[0]+cost[i-2], dp[1] + cost[i-1])
            dp[0] = dp[1]
            dp[1] = minCost
        return dp[1]
            

你可能感兴趣的:(代码随想录训练营,算法,动态规划,leetcode,python)