文章目录
买卖股票的最佳时机 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 次交易的情况。这个问题可以使用二维动态规划来解决,但同样可以通过优化减少空间复杂度至一维动态规划。
- 特殊情况处理:
○ 如果 k 大于等于 prices 长度的一半,则可以认为可以无限次交易,因为即使是最小的交易也需要两天时间(买入和卖出)。这种情况下,我们可以使用贪心算法来计算最大利润。- 动态规划:
○ 我们定义一个二维数组 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 天买入股票所能带来的最大利润。代码实现细节:
- 特殊情况处理:
○ 如果 k 大于等于 prices.length / 2,则使用 maxProfitUnlimited 函数来计算最大利润。
○ maxProfitUnlimited 函数通过遍历 prices 数组,每当价格上升时就累加利润。- 动态规划初始化:
○ 创建一个二维数组 dp,其中 dp[t][d] 用于存储在第 d 天结束时进行了 t 次交易的最大利润。
○ 初始化 maxDiff 为 -prices[0],即第一次买入股票的最大利润。- 动态规划状态转移:
○ 对于每一次交易 t,从第一天开始遍历每一天 d。
○ 更新 dp[t][d] 为 dp[t][d - 1] 和 prices[d] + maxDiff 中较大的那个值。
○ 更新 maxDiff 为 dp[t - 1][d] - prices[d] 和当前 maxDiff 中较大的那个值。- 返回最终结果:
○ 返回 dp[k][n - 1],即进行了 k 次交易后在最后一天的最大利润。结合贪心和一维DP:
● 贪心算法:
○ 当 k 大于等于 prices 长度的一半时,我们可以进行无限次交易,这时采用贪心算法,每次价格上升就卖出,累积所有上升段的利润。
● 一维DP:
○ 当 k 小于 prices 长度的一半时,使用一维DP来计算有限次交易的最大利润。
○ DP的状态定义为 dp[t][d],表示在第 d 天结束时进行了 t 次交易的最大利润。
○ 通过维护一个 maxDiff 来记录在第 d 天买入股票所能带来的最大利润,从而减少空间复杂度。