学习记录:js算法(一百一十六):买卖股票的最佳时机 IV

买卖股票的最佳时机 IV

给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:
输入:k = 2, prices = [2,4,1]
输出:2
解释:在第 1(股票价格 = 2) 的时候买入,在第 2(股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。

示例 2:
输入:k = 2, prices = [3,2,6,5,0,3]
输出:7
解释:在第 2(股票价格 = 2) 的时候买入,在第 3(股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
     随后,在第 5(股票价格 = 0) 的时候买入,在第 6(股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3

思路一


讲解
我们需要考虑最多可以进行 k 次交易的情况。这个问题可以使用二维动态规划来解决,但同样可以通过优化减少空间复杂度至一维动态规划。

  1. 特殊情况处理:
    ○ 如果 k 大于等于 prices 长度的一半,则可以认为可以无限次交易,因为即使是最小的交易也需要两天时间(买入和卖出)。这种情况下,我们可以使用贪心算法来计算最大利润。
  2. 动态规划:
    ○ 我们定义一个二维数组 dp,其中 dp[t][d] 表示在第 d 天结束时进行了 t 次交易的最大利润。
    ○ 对于每次交易 t,我们需要找到一个最大的差值 maxDiff,即在第 d 天买入股票之前最大的利润。
    ○ maxDiff 实际上代表了在第 d 天买入股票所能带来的最大利润。
    ○ 初始时,maxDiff 被设置为 -prices[0],因为我们可以在第一天买入股票。
    ○ 对于每一天 d,我们更新 dp[t][d] 为前一个状态 dp[t][d - 1] 和 prices[d] + maxDiff 中较大的那个值。
    ○ 同时,我们也更新 maxDiff 为 dp[t - 1][d] - prices[d] 和当前 maxDiff 中较大的那个值,这里 dp[t - 1][d] - prices[d] 代表在第 d 天买入股票所能带来的最大利润。

代码实现细节

  1. 特殊情况处理:
    ○ 如果 k 大于等于 prices.length / 2,则使用 maxProfitUnlimited 函数来计算最大利润。
    ○ maxProfitUnlimited 函数通过遍历 prices 数组,每当价格上升时就累加利润。
  2. 动态规划初始化:
    ○ 创建一个二维数组 dp,其中 dp[t][d] 用于存储在第 d 天结束时进行了 t 次交易的最大利润。
    ○ 初始化 maxDiff 为 -prices[0],即第一次买入股票的最大利润。
  3. 动态规划状态转移:
    ○ 对于每一次交易 t,从第一天开始遍历每一天 d。
    ○ 更新 dp[t][d] 为 dp[t][d - 1] 和 prices[d] + maxDiff 中较大的那个值。
    ○ 更新 maxDiff 为 dp[t - 1][d] - prices[d] 和当前 maxDiff 中较大的那个值。
  4. 返回最终结果:
    ○ 返回 dp[k][n - 1],即进行了 k 次交易后在最后一天的最大利润。

结合贪心和一维DP
● 贪心算法:
○ 当 k 大于等于 prices 长度的一半时,我们可以进行无限次交易,这时采用贪心算法,每次价格上升就卖出,累积所有上升段的利润。
● 一维DP:
○ 当 k 小于 prices 长度的一半时,使用一维DP来计算有限次交易的最大利润。
○ DP的状态定义为 dp[t][d],表示在第 d 天结束时进行了 t 次交易的最大利润。
○ 通过维护一个 maxDiff 来记录在第 d 天买入股票所能带来的最大利润,从而减少空间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值