代码随想录算法训练营 Day 38 || 509. 斐波那契数、70. 爬楼梯 、746. 使用最小花费爬楼梯

本文介绍了如何使用动态规划解决斐波那契数列计算和爬楼梯问题,通过状态转移方程和边界条件递推求解,展示了在两种情况下找到最优解的方法。

509. 斐波那契数

力扣题目链接(opens new window)

斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1 给你n ,请计算 F(n) 。

示例 1:

  • 输入:2
  • 输出:1
  • 解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

  • 输入:3
  • 输出:2
  • 解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

  • 输入:4
  • 输出:3
  • 解释:F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

  • 0 <= n <= 30


动态规划解决

1. 定义状态:

我们可以定义一个数组 dp,其中 dp[i] 表示斐波那契数列的第 i 个值。

2. 状态转移方程:

因为 F(n) 是由 F(n-1)F(n-2) 的和组成的,所以我们可以得到以下状态转移方程: dp[i] = dp[i-1] + dp[i-2]

3. 边界条件:
  • dp[0] = 0
  • dp[1] = 1
4. 递推计算:

i = 2 开始,使用上述的状态转移方程计算 dp[2]dp[3]... 直到 dp[n]

class Solution:
    def fib(self, n: int) -> int:
        if n <= 1:
            return n
        
        # 初始化数组
        dp = [0] * (n+1)
        dp[0] = 0
        dp[1] = 1
        
        # 自底向上递推
        for i in range(2, n+1):
            dp[i] = dp[i-1] + dp[i-2]
        
        return dp[n]

70. 爬楼梯

力扣题目链接(opens new window)

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

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

注意:给定 n 是一个正整数。

示例 1:

  • 输入: 2
  • 输出: 2
  • 解释: 有两种方法可以爬到楼顶。
    • 1 阶 + 1 阶
    • 2 阶

示例 2:

  • 输入: 3
  • 输出: 3
  • 解释: 有三种方法可以爬到楼顶。
    • 1 阶 + 1 阶 + 1 阶
    • 1 阶 + 2 阶
    • 2 阶 + 1 阶

考虑到第n个台阶的情况,你只能从第n-1或第n-2个台阶爬上来。所以到第n个台阶的方法数就是到第n-1和第n-2台阶的方法数之和。

因此,这个问题可以归纳为:

ways(n) = ways(n-1) + ways(n-2)

这与斐波那契数列是相同的。

动态规划解法:

  1. 定义状态dp[i]为到达第i个台阶的方法数。

  2. 状态转移方程dp[i] = dp[i-1] + dp[i-2]

  3. 边界条件dp[0] = 1dp[1] = 1 (第0阶有1种方法,第1阶也有1种方法)

class Solution:
    def climbStairs(self, n: int) -> int:
        if n <= 1:
            return 1

        dp = [0] * (n+1)
        dp[0] = 1
        dp[1] = 1
        
        for i in range(2, n+1):
            dp[i] = dp[i-1] + dp[i-2]

        return dp[n]

746. 使用最小花费爬楼梯

力扣题目链接(opens new window)

给你一个整数数组 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 。

def minCostClimbingStairs(cost):
    n = len(cost)
    if n == 0:
        return 0
    if n == 1:
        return cost[0]

    dp = [0] * n
    dp[0], dp[1] = cost[0], cost[1]

    for i in range(2, n):
        dp[i] = min(dp[i-1], dp[i-2]) + cost[i]

    return min(dp[n-1], dp[n-2])

# 示例
cost1 = [10,15,20]
print(minCostClimbingStairs(cost1))  # 输出:15

cost2 = [1,100,1,1,1,100,1,1,100,1]
print(minCostClimbingStairs(cost2))  # 输出:6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值