LeetCode|983. 最低票价(day12)

作者:MJ昊

博客:掘金CSDN

公众号:程序猿的编程之路

今天是 昊 的算法之路第12天,今天分享的是LeetCode第983题最低票价的解题思路。这道题目难度为中等,是一道典型的动态规划问题。

题目描述简要回顾

给定一个按升序排列的天数数组 days,表示你需要在这些天进行旅行。此外,还有三种票价和票的有效天数:

  • 一日票costs[0] 元,有效期 1 天
  • 七日票costs[1] 元,有效期 7 天
  • 三十日票costs[2] 元,有效期 30 天

你需要根据每天的出行情况,选择购买票的方式,使得总费用最低。

解题思路

  1. 动态规划状态定义

    • 使用 dp[i] 表示从第 1 天到第 i 天之间的最小总费用。
    • 如果当天不需要旅行,则 dp[i] = dp[i - 1]
    • 如果当天需要旅行,则考虑买不同票的方案,选择最小费用。
  2. 状态转移方程

    • 当天购买一日票:dp[i] = dp[i - 1] + costs[0]
    • 当天购买七日票:dp[i] = dp[i - 7] + costs[1]
    • 当天购买三十日票:dp[i] = dp[i - 30] + costs[2]
    • 对这三种方案取最小值。
  3. 优化存储

    • 使用 Set 存储需要旅行的天数,加快查找效率。
    • 遍历从第 1 天到最后一天,用动态规划数组存储结果。

代码实现:

var mincostTickets = function (days, costs) {
    const lastDay = days[days.length - 1];
    const dp = new Array(lastDay + 1).fill(0);
    const daySet = new Set(days); // 使用 Set 提高查找天数的效率
    for (let i = 1; i <= lastDay; i++) {
        if (!daySet.has(i)) {
            dp[i] = dp[i - 1]; // 如果当天不需要旅行,则费用和前一天相同
        } else {
            // 如果当天需要旅行,计算买不同类型票的最小费用
            dp[i] = Math.min(
                dp[Math.max(0, i - 1)] + costs[0], // 一日票
                dp[Math.max(0, i - 7)] + costs[1], // 七日票
                dp[Math.max(0, i - 30)] + costs[2], // 三十日票
            );
        }
    }
    return dp[lastDay]; // 返回最后一天的最小费用
};

复杂度分析##

  • 时间复杂度:O(n),其中 n 为最后一天的天数。我们需要遍历从第 1 天到 lastDay 天的所有天数,每次操作都是 O(1)。
  • 空间复杂度:O(n),动态规划数组 dp 需要存储从第 0 天到 lastDay 天的费用。

总结

这道题的关键在于理解如何构建 状态转移方程选择最优策略。通过遍历每一天并计算每种票的最小费用,我们可以在最后一天得到最优解。动态规划的思想在于通过解决子问题来构建最终解,这在处理类似问题时非常有效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值