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

news2024/10/27 7:16:41

动态规划—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]
      d p [ i ] [ j ] [ 0 ] = max ⁡ ( d p [ i − 1 ] [ j ] [ 0 ] , d p [ i − 1 ] [ j ] [ 1 ] + p r i c e s [ i ] ) dp[i][j][0] = \max(dp[i-1][j][0], dp[i-1][j][1] + prices[i]) dp[i][j][0]=max(dp[i1][j][0],dp[i1][j][1]+prices[i])
  2. 持有股票的状态

    • dp[i][j][1]:要么我们什么都不做,保持昨天持有股票的状态 dp[i-1][j][1],要么今天买入了股票,利润为 dp[i-1][j-1][0] - prices[i]
      d p [ i ] [ j ] [ 1 ] = max ⁡ ( d p [ i − 1 ] [ j ] [ 1 ] , d p [ i − 1 ] [ j − 1 ] [ 0 ] − p r i c e s [ i ] ) dp[i][j][1] = \max(dp[i-1][j][1], dp[i-1][j-1][0] - prices[i]) dp[i][j][1]=max(dp[i1][j][1],dp[i1][j1][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 问题,只需要贪心算法即可解决。

伪代码:

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代码

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++代码

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),可以通过滚动数组优化空间复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2210149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【最新华为OD机试E卷-支持在线评测】构成正方形的数量(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

(全网独家)面试要懂运维真实案例:HDFS重新平衡(HDFS Balancer)没触发问题排查

在面试时&#xff0c;面试官为了考察面试者是否真的有经验&#xff0c;经常会问运维集群时遇到什么问题&#xff0c;解决具体流程。下面是自己遇到HDFS Balancer没执行&#xff0c;花了半天时间进行排查&#xff0c;全网独家的案例和解决方案。 目录 使用CDH自带重新平衡操作…

数据结构 ——— 顺序表oj题:最长公共前缀

目录 题目要求 代码实现 题目要求 编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;如果不存在公共前缀&#xff0c;返回空字符串 "" 代码实现 代码演示&#xff1a; void CommonPrefix(char** strs, int strsSize, char* returnStr) {char* first_r…

利用session机制造测试账号,无需前端也可以测试后端接口

适用场景&#xff1a;我们在测试的时候经常会遇到前端还没有开发完毕&#xff0c;后端已经结束开发了&#xff0c;但是后端的有些接口是需要特定的账号身份调用才会生效&#xff0c;此时因为前端未开发完毕&#xff0c;所以我们不能通过web页面进行登录&#xff0c;那么如何解决…

【Python Django + Vue】酒店在线预订系统:用技术说话!

&#x1f393; 作者&#xff1a;计算机毕设小月哥 | 软件开发专家 &#x1f5a5;️ 简介&#xff1a;8年计算机软件程序开发经验。精通Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等技术栈。 &#x1f6e0;️ 专业服务 &#x1f6e0;️ 需求定制化开发源码提…

Parallels Desktop意外退出,Parallels Desktop安装软件很卡闪退怎么办?

Parallels Desktop是目前很优秀的虚拟机软件&#xff0c;操作简单&#xff0c;兼容性强而且安装也非常方便&#xff0c;备受苹果用户的喜爱和满意。然而&#xff0c;部分用户在使用Parallels Desktop的时候&#xff0c;会遇到意外退出或终端关机的情况&#xff0c;这不仅会影响…

VS2017 编译 SQLite3 动态库

首先官方下载源码: Tags sqlite/sqlite (github.com) 1.安装 VS2017 community edition 2.打开VS2017命令行工具 3.安装TCL 开发库,推荐 TCL 9.0 先下载源码: Tcl/Tk 9.0 使用vs2017编译tcl&

CRC码计算原理:按位讲解计算过程

CRC8 这里先以CRC8来说明CRC的计算过程 1、CRC8在线计算器 通过CRC在线计算器可以看见CRC8的特征多项式&#xff1a;x8x2x1&#xff0c;初始值为0000’0000。 CRC计算的核心是&#xff1a;反转异或移位&#xff08;此处的CRC8没有涉及反转&#xff0c;见后面CRC16&#xff0…

基于Langchain框架下Prompt工程调教大模型(LLM)[输入输出接口、提示词模板与例子选择器的协同应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下基于Langchain框架下Prompt工程调教大模型(LLM)[输入输出接口、提示词模板与例子选择器的协同应用。本文深入探讨了Langchain框架下的Prompt工程在调教LLM&#xff08;大语言模型&#xff09;方面的应用&#xff0c…

C++入门基础知识110—【关于C++嵌套 if 语句】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C 嵌套 if 语句的相关内容&#xff01; …

全院级、流程化的医院安全不良事件管理系统源码——等级医院评审工作的辅助工具

前言&#xff1a; 冰山理论”指出“每件严重不良事件背后可能隐藏着10件轻微的不良事件”“存在30件未造成伤害的差错可能存在600件引发意外的异常事件”没有一件不良事件应该被忽视&#xff01; 一项研究也指出95%医生曾目睹错误的发生&#xff0c;61%的医务人员认为医疗错误…

WebGL 小白入门学习

1. WebGL是什么&#xff1f; WebGL&#xff08;Web Graphics Library&#xff09;是一种JavaScript API&#xff0c;它允许你在不需要安装任何额外插件的情况下&#xff0c;直接在浏览器中渲染高性能的2D和3D图形。WebGL利用了用户的图形处理单元&#xff08;GPU&#xff09;来…

Unity 3d 鼠标设置的问题——隐藏/显示鼠标、锁定/解锁/限制鼠标、自定义鼠标形状

在unity开发的过程中&#xff0c;我们常常会遇到一些问题&#xff0c;有时会发现鼠标不见了&#xff0c;有时发现鼠标在屏幕中心不能动&#xff0c;有时又想有图片自己定义一个鼠标形状。本文将对这些问题逐一进行探讨。 一、设置鼠标的可见性 使用语句&#xff1a; Cursor.vis…

网络初识基本概念总结

网络发展背景 经历了 单机阶段 -> 局域网阶段 -> 广域网阶段 -> 移动互联网阶段 (简单介绍一下) 其他一些小概念 局域网LAN: 是把一些设备通过交换机 / 路由器连接, 形成的私有网络广域网WAN: 是把更多的局域网相互连接起来,当规模足够大时形成广域网交换机和路由器…

Rhymes AI发布首款开源多模态AI模型Aria 性能超越GPT-4o mini等多家知名AI模型

最近&#xff0c;日本东京的初创公司 Rhymes AI 推出了他们的首款人工智能模型 ——Aria。该公司自称&#xff0c;Aria 是全球首个开源的多模态混合专家&#xff08;MoE&#xff09;模型。这个模型不仅具有处理多种输入模态的能力&#xff0c;还声称在能力上与一些知名的商业模…

大一高等数学速成指南

大一高等数学速成指南 高等数学作为大学理工科学生的基础课程&#xff0c;对于许多新生来说&#xff0c;既是挑战也是机遇。本文将为你提供一个高效的学习指南&#xff0c;帮助你快速掌握高等数学的核心内容。 1. 理解课程大纲 首先&#xff0c;你需要了解高等数学的课程大纲…

Linux(1. 基本操作_命令)

目录 关于超级用户root&#xff1a; root用户可以做什么&#xff1f; 避免灾难&#xff1a; 格式约定&#xff1a; 浏览硬盘&#xff1a; 命令行补全和通配符&#xff1a; 命令行补全&#xff1a; 通配符&#xff1a; 常用基本命令&#xff1a; 查看目录和文件&#xff…

使用SpringMVC搭建WEB项目时报错404的问题排查解决以及web.xml配置文件init-param行标红问题

一、使用SpringMVC搭建WEB项目时报错404的问题排查解决 很早前&#xff08;4年前&#xff09;就把这个搭建过&#xff0c;但今天运行的时候就是报404错误&#xff0c;见文章&#xff1a; JAVA开发中SpringMVC框架的使用及常见的404问题原因以及SpringMVC框架基于注解的开发实例…

Unity3d折叠Inspector中的变量

InspectorFoldoutGroup插件 [Pixeye.Unity.Foldout("【曲线图】")] public BrokenLineUpDownGraph aimStabilityGraph;[Pixeye.Unity.Foldout("【曲线图】")] public BrokenLineUpGraph aimDensityGraph;[Pixeye.Unity.Foldout("【曲线图】")] p…

libssh2编译部署详解

libssh2编译部署详解 一、准备工作二、编译libssh2方法一:使用Autotools构建方法二:使用CMake构建三、验证安装四、使用libssh2五、结论libssh2是一个用于实现SSH2协议的开源库,它支持建立安全的远程连接、传输文件等操作。本文将详细介绍如何在Linux系统下编译和部署libssh…