首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【LeetCode】动态规划—188. 买卖股票的最佳时机 IV(附完整Python/C++代码)

【LeetCode】动态规划—188. 买卖股票的最佳时机 IV(附完整Python/C++代码)

作者头像
用户9613193
发布2026-06-16 19:38:23
发布2026-06-16 19:38:23
510
举报
动态规划—188. 买卖股票的最佳时机 IV

  • 题目描述
  • 前言
  • 基本思路
    • 1. 问题定义
      • 交易规则:
    • 2. 理解问题和递推关系
      • 两种情况:
      • 状态定义:
      • 状态转移方程:
      • 初始条件:
    • 3. 解决方法
      • 动态规划方法
      • 特殊情况:当 `k` 大于等于 `prices` 长度的一半时
      • 伪代码:
    • 4. 进一步优化
    • 5. 小总结
  • Python代码
      • Python代码解释总结:
  • C++代码
      • C++代码解释总结:
  • 最终总结

题目描述

在这里插入图片描述
在这里插入图片描述

前言

买卖股票的最佳时机 IV 是股票交易系列问题中的一个变种,难度较高。该问题要求我们最多进行 k 次交易,每次交易包含一次买入和一次卖出,目标是通过这 k 次交易获取最大利润。该问题结合了 动态规划贪心 的思想,要求我们合理规划每次买卖的时机以获取最大利润。


基本思路

1. 问题定义

给定一个整数 k,表示最多可以进行的交易次数,以及一个整数数组 prices,其中 prices[i] 表示股票第 i 天的价格,目标是计算最多进行 k 次交易可以获得的最大利润。

交易规则:
  • 每次交易必须包含买入和卖出。
  • 同一天不能同时进行买入和卖出。
  • 你可以在一天内完成一次交易,即买入和卖出可以在同一天发生。

2. 理解问题和递推关系

两种情况:
  1. 如果 k 大于等于 prices 的一半,那么我们可以进行无限次交易,问题退化为类似 无限次交易 的问题,可以用贪心策略来解决。
  2. 如果 k 小于 prices 的一半,那么我们需要用动态规划来解决问题,控制交易次数。
状态定义:

我们可以定义 dp[i][j][0]dp[i][j][1] 来表示在第 i 天结束时,最多进行了 j 次交易的两种状态:

  • dp[i][j][0] 表示第 i 天结束时,没有持有股票,最多进行了 j 次交易的最大利润。
  • dp[i][j][1] 表示第 i 天结束时,持有股票,最多进行了 j 次交易的最大利润。
状态转移方程:
  1. 不持有股票的状态
    • dp[i][j][0]:要么我们什么都不做,保持昨天不持有股票的状态 dp[i-1][j][0],要么今天卖出了股票,利润为 dp[i-1][j][1] + prices[i]
    dp[i][j][0] = \max(dp[i-1][j][0], dp[i-1][j][1] + prices[i])
  2. 持有股票的状态
    • dp[i][j][1]:要么我们什么都不做,保持昨天持有股票的状态 dp[i-1][j][1],要么今天买入了股票,利润为 dp[i-1][j-1][0] - prices[i]
    dp[i][j][1] = \max(dp[i-1][j][1], dp[i-1][j-1][0] - prices[i])
初始条件:
  • dp[0][j][0] = 0:在第 0 天结束时,没有进行任何交易的利润为 0。
  • dp[0][j][1] = -prices[0]:在第 0 天结束时,如果持有股票,则利润为 -prices[0]

3. 解决方法

动态规划方法
  1. 初始化 dp 数组,表示每天结束时,最多进行 j 次交易的最大利润。
  2. 根据状态转移方程,逐步更新每一天的状态。
  3. 最终结果为 dp[n-1][k][0],表示在第 n-1 天结束时,不持有股票且最多进行了 k 次交易的最大利润。
特殊情况:当 k 大于等于 prices 长度的一半时

如果 k >= len(prices) // 2,那么问题退化为可以进行无限次交易的情况,类似于买卖股票 II 问题,只需要贪心算法即可解决。

伪代码:
代码语言:javascript
复制
if k >= len(prices) // 2:
    return solve_unlimited_transactions()

initialize dp array with dimensions (n, k+1, 2)
for each day i from 1 to n-1:
    for each transaction j from 1 to k:
        update dp[i][j][0] and dp[i][j][1] using state transition formulas
return dp[n-1][k][0]

4. 进一步优化

  • 空间优化:可以通过滚动数组,将 dp[i][j][0]dp[i][j][1] 仅用两层数组存储,降低空间复杂度。

5. 小总结

  • 问题思路:通过动态规划,定义持有股票和不持有股票的状态,并根据交易次数进行状态转移。
  • 时间复杂度:时间复杂度为 O(n*k),适合处理中等规模的 nk

以上就是买卖股票的最佳时机 IV问题的基本思路。


Python代码

代码语言:javascript
复制
class Solution:
    def maxProfit(self, k: int, prices: list[int]) -> int:
        if not prices:
            return 0
        
        n = len(prices)

        # 当 k 大于等于 n/2 时,相当于可以进行无限次交易
        if k >= n // 2:
            max_profit = 0
            for i in range(1, n):
                if prices[i] > prices[i - 1]:
                    max_profit += prices[i] - prices[i - 1]
            return max_profit

        # 初始化 dp 数组
        dp = [[[0, 0] for _ in range(k + 1)] for _ in range(n)]
        
        # 初始化第一天的状态
        for j in range(1, k + 1):
            dp[0][j][1] = -prices[0]

        # 动态规划状态转移
        for i in range(1, n):
            for j in range(1, k + 1):
                dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i])
                dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i])

        # 返回结果
        return dp[n - 1][k][0]
Python代码解释总结:
  1. 特殊情况处理:当 k >= len(prices) // 2 时,问题转化为无限次交易,通过贪心策略解决。
  2. 初始化和状态转移:通过动态规划状态转移公式,更新 dp[i][j][0]dp[i][j][1]
  3. 返回结果:最终返回 dp[n-1][k][0],即不持有股票且进行了 k 次交易的最大利润。

C++代码

代码语言:javascript
复制
class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n = prices.size();
        if (n == 0) return 0;

        // 当 k 大于等于 n/2 时,相当于可以进行无限次交易
        if (k >= n / 2) {
            int max_profit = 0;
            for (int i = 1; i < n; ++i) {
                if (prices[i] > prices[i - 1]) {
                    max_profit += prices[i] - prices[i - 1];
                }
            }
            return max_profit;
        }

        // 初始化 dp 数组
        vector<vector<vector<int>>> dp(n, vector<vector<int>>(k + 1, vector<int>(2, 0)));

        // 初始化第一天的状态
        for (int j = 1; j <= k; ++j) {
            dp[0][j][1] = -prices[0];
        }

        // 动态规划状态转移
        for (int i = 1; i < n; ++i) {
            for (int j = 1; j <= k; ++j) {
                dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
                dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
            }
        }

        // 返回结果
        return dp[n - 1][k][0];
    }
};
C++代码解释总结:
  1. 处理无限次交易的情况:当 k >= n // 2 时,问题退化为可以进行无限次交易,用贪心算法解决。
  2. 状态转移:通过动态规划更新 dp[i][j][0]dp[i][j][1]
  3. 返回结果:返回 dp[n-1][k][0],即最大利润。

最终总结

  • 核心思想:通过动态规划,分为持有股票和不持有股票两种状态,并根据交易次数进行状态转移。通过 dp[i][j][0]dp[i][j][1] 来跟踪每一天、每一次交易的利润状态。
  • 时间复杂度:时间复杂度为 O(n*k),空间复杂度为 O(n*k),可以通过滚动数组优化空间复杂度。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 动态规划—188. 买卖股票的最佳时机 IV
  • 题目描述
  • 前言
  • 基本思路
    • 1. 问题定义
      • 交易规则:
    • 2. 理解问题和递推关系
      • 两种情况:
      • 状态定义:
      • 状态转移方程:
      • 初始条件:
    • 3. 解决方法
      • 动态规划方法
      • 特殊情况:当 k 大于等于 prices 长度的一半时
      • 伪代码:
    • 4. 进一步优化
    • 5. 小总结
  • Python代码
    • Python代码解释总结:
  • C++代码
    • C++代码解释总结:
  • 最终总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档