当前位置: 首页 > news >正文

DAY40|动态规划Part08|LeetCode: 121. 买卖股票的最佳时机 、 122.买卖股票的最佳时机II 、 123.买卖股票的最佳时机III

目录

LeetCode:121. 买卖股票的最佳时机

暴力解法

贪心法

动态规划法

LeetCode:122.买卖股票的最佳时机II

基本思路

LeetCode:  买卖股票的最佳时机III、IV

基本思路

C++代码


LeetCode:121. 买卖股票的最佳时机

力扣题目链接

文字讲解:121. 买卖股票的最佳时机

视频讲解:动态规划之 LeetCode:121.买卖股票的最佳时机1

暴力解法

class Solution {
public:int maxProfit(vector<int>& prices) {int result = 0;for (int i = 0; i < prices.size(); i++) {for (int j = i + 1; j < prices.size(); j++){result = max(result, prices[j] - prices[i]);}}return result;}
};

        但是很容易看出时间复杂度为O(n^2)----超时!

贪心法

        因为股票就买卖一次,那么贪心的想法很自然就是取最左最小值,取最右最大值,那么得到的差值就是最大利润。

class Solution {
public:int maxProfit(vector<int>& prices) {int low = INT_MAX;int result = 0;for (int i = 0; i < prices.size(); i++) {low = min(low, prices[i]);  // 取最左最小价格result = max(result, prices[i] - low); // 直接取最大区间利润}return result;}
};

动态规划法

动规五部曲分析如下:

  • 确定dp数组(dp table)以及下标的含义

        dp[i][0]表示第i天持有股票(当然也可以表示为不持有股票,但如果这样设置那么在确定递推公式时连续性不明显,在最佳时机III中能比较明显的体会到)所得最多现金。dp[i][1]表示第i天不持有股票所得最多现金。

  • 确定递推公式

        dp[i][0]和dp[i][1]应该分开计算。

        对于dp[i][0]来说,存在两种情况,一种是第i-1天同样持有股票,另一种是第i-1天不持有股票,在第i天买入,此时dp[i][0] = max(dp[i-1][0],dp[i-1][1] - price[i]);

        同理,对于dp[i][1]同样有两种情况,dp[i][1] = max(dp[i-1][1],dp[i-1][0] + price[i]);

  • dp数组如何初始化

        由递推公式可以看出,其基础都是要从dp[0][0]和dp[0][1]推导出来的,所以dp[0][0]表示第一天持有股票,即第一天买入,此时最大金额为-price[0];dp[0][1]表示第一天不持有股票,即为初试金额0。

  • 确定遍历顺序

        从递推公式可以看出dp[i]都是由dp[i - 1]推导出来的,那么一定是从前向后遍历。

  • 举例推导dp数组

        以示例1,输入:[7,1,5,3,6,4]为例,dp数组状态如下:

        显然,最后的结果一定是dp[5][0]和dp[5][1]中的一个结果,那么应该选择哪一个呢?其实仔细想想很容易得出,持有股票所拥有的金额一定小于不持有股票的金额,因此最后返回值为dp[5][1]。

// 版本一
class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();if (len == 0) return 0;vector<vector<int>> dp(len, vector<int>(2));dp[0][0] -= prices[0];dp[0][1] = 0;for (int i = 1; i < len; i++) {dp[i][0] = max(dp[i - 1][0], -prices[i]);dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);}return dp[len - 1][1];}
};

        当然这样的时间复杂度和空间复杂度都是O(n)。从递推公式可以看出,dp[i]只是依赖于dp[i - 1]的状态。那么我们只需要记录 当前天的dp状态和前一天的dp状态就可以了,可以使用滚动数组来节省空间。

// 版本二
class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();vector<vector<int>> dp(2, vector<int>(2)); // 注意这里只开辟了一个2 * 2大小的二维数组dp[0][0] -= prices[0];dp[0][1] = 0;for (int i = 1; i < len; i++) {dp[i % 2][0] = max(dp[(i - 1) % 2][0], -prices[i]);dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);}return dp[(len - 1) % 2][1];}
};

LeetCode:122.买卖股票的最佳时机II

力扣题目链接

文字讲解:LeetCode:122.买卖股票的最佳时机II

视频讲解:动态规划,股票问题第二弹 | LeetCode:122.买卖股票的最佳时机II

基本思路

        和买卖股票的最佳时机的步骤基本一致,不同点在于本题可以不限次数的购买股票,因此递推公式需要进行改变:

dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i]);

dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i]);

class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();vector<vector<int>> dp(len, vector<int>(2, 0));dp[0][0] -= prices[0];dp[0][1] = 0;for (int i = 1; i < len; i++) {dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); // 注意这里是和121. 买卖股票的最佳时机唯一不同的地方。dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);}return dp[len - 1][1];}
};

        当然同样为了降低空间复杂度,可以采用滚动数组的方法。

// 版本二
class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();vector<vector<int>> dp(2, vector<int>(2)); // 注意这里只开辟了一个2 * 2大小的二维数组dp[0][0] -= prices[0];dp[0][1] = 0;for (int i = 1; i < len; i++) {dp[i % 2][0] = max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] - prices[i]);dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);}return dp[(len - 1) % 2][1];}
};

LeetCode:  买卖股票的最佳时机III、IV

题目:123. 买卖股票的最佳时机 III、188. 买卖股票的最佳时机 IV

文字讲解: 123.买卖股票的最佳时机III、188. 买卖股票的最佳时机 IV

视频讲解:动态规划,股票至多买卖两次,怎么求? | LeetCode:123.买卖股票最佳时机III

基本思路

        买卖股票的最佳时机III这个题目要求最多出手两次,使所获得的利益最大化。而最佳时机IV则是引申到了n次。因此可以先通过最佳时机III进行分析。

动规五部曲分析如下:

  • 确定dp数组(dp table)以及下标的含义

        首先,如果至多出手三次,那么我们就存在5种状态,即dp[0][0]表示第一天第0次不持有股票(即初始状态)所获的最大金额,即dp[0][1]表示第一天第一次持有股票(即第一次买入时的状态)所获的最大金额,即dp[0][2]表示第一次不持有股票(即第一次卖出时的状态)所获的最大金额,即dp[0][3]表示第一天第二次持有股票所获的最大金额,即dp[0][4]表示第一天第二次不持有股票所获的最大金额。

  • 确定递推公式

        dp[i][0] = dp[i-1][0];

        dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i]);

        dp[i][2] = max(dp[i-1][2],dp[i-1][1] + prices[i]);

        dp[i][3] = max(dp[i-1][3],dp[i-1][2] - prices[i]);

        dp[i][4] = max(dp[i-1][4],dp[i-1][3] + prices[i]);

  • dp数组如何初始化

        数组初始化为0,并且dp[0][1] = -prices[0];以及dp[0][3] = -prices[0];

  • 确定遍历顺序

        从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。

  • 举例推导dp数组

        以输入[1,2,3,4,5]为例。

C++代码

// 版本一
class Solution {
public:int maxProfit(vector<int>& prices) {if (prices.size() == 0) return 0;vector<vector<int>> dp(prices.size(), vector<int>(5, 0));dp[0][1] = -prices[0];dp[0][3] = -prices[0];for (int i = 1; i < prices.size(); i++) {dp[i][0] = dp[i - 1][0];dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i]);dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]);dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]);}return dp[prices.size() - 1][4];}
};

        同样,可以使用滚动数组进行优化。

// 版本二
class Solution {
public:int maxProfit(vector<int>& prices) {if (prices.size() == 0) return 0;vector<int> dp(5, 0);dp[1] = -prices[0];dp[3] = -prices[0];for (int i = 1; i < prices.size(); i++) {dp[1] = max(dp[1], dp[0] - prices[i]);dp[2] = max(dp[2], dp[1] + prices[i]);dp[3] = max(dp[3], dp[2] - prices[i]);dp[4] = max(dp[4], dp[3] + prices[i]);}return dp[4];}
};

相关文章:

DAY40|动态规划Part08|LeetCode: 121. 买卖股票的最佳时机 、 122.买卖股票的最佳时机II 、 123.买卖股票的最佳时机III

目录 LeetCode:121. 买卖股票的最佳时机 暴力解法 贪心法 动态规划法 LeetCode:122.买卖股票的最佳时机II 基本思路 LeetCode: 买卖股票的最佳时机III、IV 基本思路 C代码 LeetCode:121. 买卖股票的最佳时机 力扣题目链接 文字讲解&#xff1a;121. 买卖股票的最佳时…...

【安装及调试旧版Chrome + 多版本环境测试全攻略】

&#x1f468;&#x1f4bb; 安装及调试旧版Chrome 多版本环境测试全攻略 &#x1f310; &#xff08;新手友好版 | 覆盖安装/运行/调试全流程&#xff09; &#x1f570;️ 【背景篇】为什么我们需要旧版浏览器测试&#xff1f; &#x1f30d; &#x1f310; 浏览器世界的“…...

【Linux】进程间通信——命名管道

文章目录 命名管道什么是命名管道**命名管道 vs. 无名管道**如何创建命名管道 用命名管道实现进程间通信MakefileComm.hppServer.hppClient.hppServer.cppClient.cpp 效果总结 命名管道 什么是命名管道 命名管道&#xff0c;也称为 FIFO&#xff08;First In First Out&#…...

Qt在Linux嵌入式开发过程中复杂界面滑动时卡顿掉帧问题分析及解决方案

Qt在Linux嵌入式设备开发过程中&#xff0c;由于配置较低&#xff0c;加上没有GPU&#xff0c;我们有时候会遇到有些组件比较多的复杂界面&#xff0c;在滑动时会出现掉帧或卡顿的问题。要讲明白这个问题还得从CPU和GPU的分工说起。 一、硬件层面核心问题根源剖析 CPU&#x…...

AI学习第六天-python的基础使用-趣味图形

在 Python 编程学习过程中&#xff0c;turtle库是一个非常有趣且实用的工具&#xff0c;它可以帮助我们轻松绘制各种图形。结合for循环、random模块以及自定义方法等知识点&#xff0c;能够创作出丰富多彩的图案。下面就来分享一下相关的学习笔记。 一、基础知识点回顾 &…...

[VMware]卸载VMware虚拟机和Linux系统ubuntu(自记录版)

记录一下,不是教程,只是防止我做错了可以回溯一下 我打开vscode,就会跳出下图 虚拟机,Linux还是很久之前学习安装的,种途可能卸载过(不太记得了),现在尝试彻底卸载 彻底卸载VMware虚拟机的详细步骤-CSDN博客虚拟机Vmware 转移 克隆 卸载及移除Linux系统_克隆的虚拟机怎么移除-…...

J-LangChain,用Java实现LangChain编排!轻松加载PDF、切分文档、向量化存储,再到智能问答

Java如何玩转大模型编排、RAG、Agent&#xff1f;&#xff1f;&#xff1f; 在自然语言处理&#xff08;NLP&#xff09;的浪潮中&#xff0c;LangChain作为一种强大的模型编排框架&#xff0c;已经在Python社区中广受欢迎。然而&#xff0c;对于Java开发者来说&#xff0c;能…...

Cuppa CMS v1.0 任意文件读取(CVE-2022-25401)

漏洞简介&#xff1a; Cuppa CMS v1.0 administrator/templates/default/html/windows/right.php文件存在任意文件读取漏洞 漏洞环境&#xff1a; 春秋云镜中的漏洞靶标&#xff0c;CVE编号为CVE-2022-25401 漏洞复现 弱口令行不通 直接访问administrator/templates/defau…...

可以免费无限次下载PPT的网站

前言 最近发现了一个超实用的网站&#xff0c;想分享给大家。 在学习和工作的过程中&#xff0c;想必做PPT是一件让大家都很头疼的一件事。 想下载一些PPT模板减少做PPT的工作量&#xff0c;但网上大多精美的PPT都是需要付费才能下载使用。 即使免费也有次数限制&#xff0…...

STM32中使用PWM对舵机控制

目录 1、硬件JIE 2、PWM口配置 3、角度转换 4、main函数中应用 5、工程下载连接 1、硬件介绍 单片机&#xff1a;STM32F1 舵机&#xff1a;MG995 2、PWM口配置 20毫秒的PWM脉冲占空比&#xff0c;对舵机控制效果较好 计算的公式&#xff1a; PSC、ARR值的选取&#xf…...

使用插件 `vue2-water-marker`添加全局水印

使用插件 vue2-water-marker添加全局水印 效果图 1、安装插件 npm install vue2-water-marker --save2、全局注册 // main.js import Vue from vue import Vue2WaterMarker from vue2-water-markerVue.use(Vue2WaterMarker)3、在组件中使用 <template><div id&q…...

MySQL表约束的种类与应用

在MySQL数据库中&#xff0c;表约束是确保数据完整性的关键。约束限制了可以在表中插入或更新的数据类型&#xff0c;保证数据的准确性和可靠性。了解MySQL中的各种表约束对于数据库设计和数据维护至关重要。以下是MySQL支持的主要表约束类型及其应用的详细介绍。 1. 主键约束…...

【大模型+知识图谱】大模型与知识图谱融合:技术演进、实践应用与未来挑战

【大模型+知识图谱】大模型与知识图谱融合:技术演进、实践应用与未来挑战 大模型与知识图谱融合:技术演进、实践应用与未来挑战引言:为什么需要融合?一、技术融合的三重路径1.1 知识图谱增强大模型1.2 大模型赋能知识图谱1.3 协同推理框架二、工业级应用场景落地2.1 智能问…...

MS SQL 2008 技术内幕:T-SQL 语言基础

《MS SQL 2008 技术内幕&#xff1a;T-SQL 语言基础》是一部全面介绍 Microsoft SQL Server 2008 中 T-SQL&#xff08;Transact-SQL&#xff09;语言的书籍。T-SQL 是 SQL Server 的扩展版本&#xff0c;增加了编程功能和数据库管理功能&#xff0c;使得开发者和数据库管理员能…...

MySQL-MATCH ... AGAINST工具

在MySQL中&#xff0c;MATCH……AGAINST是全文索引&#xff08;Full-Text index&#xff09;的查询语法&#xff0c;它允许你对文本进行高效的全文搜素&#xff0c;支持自然语言搜索和布尔搜索模式。以下是MATCH……AGAINST的详细用法和示例 一、全文索引的基本概念 全文索引适…...

微服务合并

有的团队为了节约机器成本、有的团队为了提升研发效率、有的团队为了降低人均服务数 微服务合并&#xff0c;可以从多个角度入手 代码重构融合&#xff1a;人工拷贝代码、解决冲突&#xff0c;然后分阶段实施迁移重构。代码合并打包&#xff1a;将多个代码仓库&#xff0c;拉取…...

Shell脚本基础:用Bash自动化任务

Shell脚本基础&#xff1a;用Bash自动化任务 在Linux运维中&#xff0c;手动执行重复性任务既耗时又容易出错&#xff0c;而Shell脚本则为自动化提供了强大支持。 从基础概念到实用案例&#xff0c;逐步掌握用Bash实现自动化的核心技能。Shell脚本是Linux自动化的基石&#xf…...

基于W2605C语音识别合成芯片的智能语音交互闹钟方案-AI对话享受智能生活

随着科技的飞速发展&#xff0c;智能家居产品正逐步渗透到我们的日常生活中&#xff0c;其中智能闹钟作为时间管理的得力助手&#xff0c;也在不断进化。基于W2605C语音识别与语音合成芯片的智能语音交互闹钟&#xff0c;凭借其强大的联网能力、自动校时功能、实时天气获取、以…...

【Java项目】基于Spring Boot的网上商城购物系统

【Java项目】基于Spring Boot的网上商城购物系统 技术简介&#xff1a;采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介&#xff1a;系统实现管理员&#xff1a;首页、个人中心、用户管理、商品分类管理、商品信息管理、订单评价管理、系统管理、订单管理&#x…...

开放标准(RFC 7519):JSON Web Token (JWT)

开放标准&#xff1a;JSON Web Token 前言基本使用整合Shiro登录自定义JWT认证过滤器配置Config自定义凭证匹配规则接口验证权限控制禁用session缓存的使用登录退出单用户登录Token刷新双Token方案单Token方案 前言 JSON Web Token &#xff08;JWT&#xff09; 是一种开放标准…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

图解JavaScript原型:原型链及其分析 | JavaScript图解

​​ 忽略该图的细节&#xff08;如内存地址值没有用二进制&#xff09; 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么&#xff1a;保存在堆中一块区域&#xff0c;同时在栈中有一块区域保存其在堆中的地址&#xff08;也就是我们通常说的该变量指向谁&…...

【阅读笔记】MemOS: 大语言模型内存增强生成操作系统

核心速览 研究背景 ​​研究问题​​&#xff1a;这篇文章要解决的问题是当前大型语言模型&#xff08;LLMs&#xff09;在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色&#xff0c;但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成&#xff08;RA…...

python打卡day49@浙大疏锦行

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 一、通道注意力模块复习 & CBAM实现 import torch import torch.nn as nnclass CBAM(nn.Module):def __init__…...