代码随想录算法训练营day49 | 动态规划 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV
day49
- 123.买卖股票的最佳时机III
- 1.确定dp数组以及下标的含义
- 2.确定递推公式
- 3.dp数组如何初始化
- 4.确定遍历顺序
- 5.举例推导dp数组
- 188.买卖股票的最佳时机IV
- 1.确定dp数组以及下标的含义
- 2.确定递推公式
- 4.dp数组如何初始化
- 4.确定遍历顺序
- 5.举例推导dp数组
123.买卖股票的最佳时机III
题目链接
解题思路: 关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。
动规五部曲
1.确定dp数组以及下标的含义
一天一共就有五个状态,
- 没有操作 (其实我们也可以不设置这个状态)
- 第一次持有股票
- 第一次不持有股票
- 第二次持有股票
- 第二次不持有股票
dp[i][j]
中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]
表示第i天状态j所剩最大现金。
需要注意:dp[i][1]
,表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票
例如 dp[i][1]
,并不是说 第i天一定买入股票,有可能 第 i-1天 就买入了,那么 dp[i][1]
延续买入股票的这个状态。
2.确定递推公式
达到dp[i][1]
状态,有两个具体操作:
- 操作一:第i天买入股票了,那么
dp[i][1] = dp[i-1][0] - prices[i]
- 操作二:第i天没有操作,而是沿用前一天买入的状态,即:
dp[i][1] = dp[i - 1][1]
那么dp[i][1]
究竟选 dp[i-1][0] - prices[i]
,还是dp[i - 1][1]
呢?
一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1])
;
同理dp[i][2]
也有两个操作:
- 操作一:第i天卖出股票了,那么
dp[i][2] = dp[i - 1][1] + prices[i]
- 操作二:第i天没有操作,沿用前一天卖出股票的状态,即:
dp[i][2] = dp[i - 1][2]
所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])
同理可推出剩下状态部分:
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]);
3.dp数组如何初始化
第0天没有操作,这个最容易想到,就是0,即:dp[0][0] = 0
;
第0天做第一次买入的操作,dp[0][1] = -prices[0]
;
第0天做第一次卖出的操作,这个初始值应该是多少呢?
此时还没有买入,怎么就卖出呢? 其实大家可以理解当天买入,当天卖出,所以dp[0][2] = 0
;
第0天第二次买入操作,初始值应该是多少呢?应该不少同学疑惑,第一次还没买入呢,怎么初始化第二次买入呢?
第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后再买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。
所以第二次买入操作,初始化为:dp[0][3] = -prices[0];
同理第二次卖出初始化dp[0][4] = 0;
4.确定遍历顺序
从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]
的数值。
5.举例推导dp数组
以输入[1,2,3,4,5]为例
大家可以看到红色框为最后两次卖出的状态。
整体代码如下:
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];}
};
188.买卖股票的最佳时机IV
题目链接
解题思路:
动规五部曲如下
1.确定dp数组以及下标的含义
在动态规划:123.买卖股票的最佳时机III 中,我是定义了一个二维dp数组,本题其实依然可以用一个二维dp数组。
使用二维数组 dp[i][j]
:第i天的状态为j,所剩下的最大现金是dp[i][j]
j的状态表示为:
- 0 表示不操作
- 1 第一次买入
- 2 第一次卖出
- 3 第二次买入
- 4 第二次卖出
…
题目要求是至多有K笔交易,那么j的范围就定义为 2 * k + 1
就可以了。
所以二维dp数组的C++定义为:
vector<vector<int>> dp(prices.size(), vector<int>(2 * k + 1, 0));
2.确定递推公式
还要强调一下:dp[i][1]
,表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票,这是很多同学容易陷入的误区。
达到dp[i][1]
状态,有两个具体操作:
- 操作一:第i天买入股票了,那么
dp[i][1] = dp[i - 1][0] - prices[i]
- 操作二:第i天没有操作,而是沿用前一天买入的状态,即:
dp[i][1] = dp[i - 1][1]
选最大的,所以 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1])
;
同理dp[i][2]
也有两个操作:
- 操作一:第i天卖出股票了,那么
dp[i][2] = dp[i - 1][1] + prices[i]
- 操作二:第i天没有操作,沿用前一天卖出股票的状态,即:
dp[i][2] = dp[i - 1][2]
所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])
同理可以类比剩下的状态,代码如下:
for (int j = 0; j < 2 * k - 1; j += 2) {dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]);
}
本题和动态规划:123.买卖股票的最佳时机III 最大的区别就是这里要类比j为奇数是买,偶数是卖的状态。
4.dp数组如何初始化
第0天没有操作,这个最容易想到,就是0,即:dp[0][0] = 0
;
第0天做第一次买入的操作,dp[0][1] = -prices[0]
;
第0天做第一次卖出的操作,这个初始值应该是多少呢?
此时还没有买入,怎么就卖出呢? 其实大家可以理解当天买入,当天卖出,所以dp[0][2] = 0;
第0天第二次买入操作,初始值应该是多少呢?应该不少同学疑惑,第一次还没买入呢,怎么初始化第二次买入呢?
第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后在买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。
所以第二次买入操作,初始化为:dp[0][3] = -prices[0]
;
第二次卖出初始化dp[0][4] = 0
;
所以同理可以推出dp[0][j]
当j为奇数的时候都初始化为 -prices[0]
代码如下:
for (int j = 1; j < 2 * k; j += 2) {dp[0][j] = -prices[0];
}
在初始化的地方同样要类比j为偶数是卖、奇数是买的状态。
4.确定遍历顺序
从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i]
,依靠dp[i - 1]
的数值。
5.举例推导dp数组
以输入[1,2,3,4,5],k=2为例。
最后一次卖出,一定是利润最大的,dp[prices.size() - 1][2 * k]
即红色部分就是最后求解。
C++代码如下:
class Solution {
public:int maxProfit(int k, vector<int>& prices) {if (prices.size() == 0) return 0;vector<vector<int>> dp(prices.size(), vector<int>(2 * k + 1, 0));for (int j = 1; j < 2 * k; j += 2) {dp[0][j] = -prices[0];}for (int i = 1;i < prices.size(); i++) {for (int j = 0; j < 2 * k - 1; j += 2) {dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]);}}return dp[prices.size() - 1][2 * k];}
};
相关文章:

代码随想录算法训练营day49 | 动态规划 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV
day49123.买卖股票的最佳时机III1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组188.买卖股票的最佳时机IV1.确定dp数组以及下标的含义2.确定递推公式4.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组123.买卖股票的最佳时机III …...

【教学典型案例】14.课程推送页面整理-增加定时功能
目录一:背景介绍1、代码可读性差,结构混乱2、逻辑边界不清晰,封装意识缺乏3、展示效果不美观二:案例问题分析以及解决过程1、代码可读性…...
【算法基础】DFS BFS 进阶训练
DFS与BFS的基础篇详见:https://blog.csdn.net/m0_51339444/article/details/129301451?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129301451%22%2C%22source%22%3A%22m0_51339444%22%7D 一、案例分析1 (树的重心 —— D…...
GO语言中的回调函数
0.前言 回调函数是一种在编程中常见的技术,通常在异步编程中使用。简单来说,回调函数是一个被传递给另一个函数的函数,它在该函数的某个时间点被调用,以完成某些特定的操作或任务。 在Go语言中,可以将函数直接作为参…...

28个案例问题分析---014课程推送页面逻辑整理--vue
一:背景介绍 项目开发过程中,前端出现以下几类问题: 代码结构混乱代码逻辑不清晰页面细节问题 二:问题分析 代码结构混乱问题 <template><top/><div style"position: absolute;top: 10px"><C…...
佛科院单片机原理2——80C51单片机结构
一、程序存储器的入口地址:程序入口地址:0000H外部中断0入口地址:0003H定时器0溢出中断入口地址:000BH外部中断1入口地址:00013H定时器1溢出中断入口地址:001BH串行口中断入口地址:0023H定时器2…...
数据结构与算法_动态顺序表
顺序表是线性表的一种。 线性表是n个具有相同特性的数据元素的有限序列。 逻辑上,它们是线性结构,是一条连续的直线;但是在物理上,它们通常以数组和链式结构存储。 常见的线性表有顺序表、栈、队列、字符串等。 顺序表是用一段…...
逃避浏览器JS检测打开开发者工具
20230304 - 0. 引言 看到一些视频网站之后,想把视频离线下载下来怎么办?直接的方法是通过开发者工具来查看网络流量,一般可以在传输的请求类型中搜索m3u8,然后找到这部分请求,然后利用某些播放器或者下载器直接下载。…...

ceph介绍、原理、架构、算法...个人学习记录
前言 之前公司安排出差支援非结构化项目,采用springcloud(redismysql数据冷热处理)s3escephkafka还涉及一些区块链技术等等…,在与大佬的沟通交流下对ceph产生了兴趣,私下学习记录一下;后续工作之余会采用上面相关技术栈手动实现不…...

Spring MVC源码解析——HandlerMapping(处理器映射器)
Sping MVC 源码解析——HandlerMapping处理器映射器1. 什么是HandlerMapping2. HandlerMapping2.1 HandlerMapping初始化2.2 getHandler解析3. getHandlerInternal()子类实现3.1 AbstractUrlHandlerMapping与AbstractHandlerMethodMapping的区别3.2 AbstractUrlHandlerMapping3…...

【Word/word2007】将标题第1章改成第一章
问题:设置多级列表没有其他格式选的解决办法和带来的插入图注解的问题,将标题第1章改成第一章的问题其他方案。 按照百度搜索的方法设置第一章,可以是没有相应的样式可以选。 那就换到编号选项 设置新的编号值 先选是 然就是变得很丑 这时打开…...

NLP预训练模型
Models Corpus RoBERTa: A Robustly Optimized BERT Pretraining Approach 与BERT主要区别在于: large mini-batches 保持总训练tokens数一致,使用更大的学习率、更大的batch size,adam β20.98\beta_20.98β20.98;dynamic ma…...

Typora上传文档图片链接失效的问题+PicGo布置图床在Github
文章目录typora图片链接失效原因PicGO开源图床布置先配置Github2.1先创建新仓库、用于存放图片2.2生成一个token,用picGo访问github3.下载picGo,并进行配置3.1 配置v4.1typora图片链接失效原因 因为你是保存在本地的,因此图片是不能访问,可以…...

win10安装oracle
文件放到最后。我的电脑是win11的,因为老师让写下安装笔记,在11上安装的时候没有截屏,所以在虚拟机上重新安装下吧。室友说要把文件夹放到c盘才能打开。我试了下,具体的是要把Oracle11g文件夹放到c盘根目录下。如果解压后不是这个…...

AQS为什么用双向链表?
首先,在AQS中,等待队列是通过Node类来表示的,每个Node节点包含了等待线程的信息以及等待状态。下面是Node类的部分源码:static final class Node {// 等待状态volatile int waitStatus;// 前驱节点volatile Node prev;// 后继节点…...
AtCoder Beginner Contest 292——A-E题讲解
蒟蒻来讲题,还望大家喜。若哪有问题,大家尽可提! Hello, 大家好哇!本初中生蒟蒻讲解一下AtCoder Beginner Contest 292这场比赛的A-E题! A题 原题 Problem Statement You are given a string SSS consisting of lo…...

(蓝桥真题)最长不下降子序列(权值线段树)
样例输入: 5 1 1 4 2 8 5 样例输出: 4 分析:看到这种对其中连续k个数进行修改的我们就应该想到答案是由三部分组成,因为求的是最长不下降子序列,那么我们可以找到一个最合适的断点i,使得答案是由区间[1…...
数据类型及参数传递
1.数据类型 java中的基本数据类型: 数值型: 整数型:byte short long int 浮点型:float double 布尔型: boolean字符串: char java中的引用数据类型: 数组(array) 类(class…...

永春堂1300系统开发|解析永春堂1300模式商城的五大奖项
电商平台竞争越来越激烈,各种营销方式也是层出不穷,其中永春堂1300营销模式,以其无泡沫和自驱动性强等特点风靡一时。在这套模式中,虽然单型价格差异较大,但各种奖励的设计,巧妙的兼顾了平台和所有会员的利…...

最近一年我都干了什么——反思!!
过去一年不管是学习方式还是心态上都和以往有了许多不同的地方,比较昏昏沉沉。最近慢慢找到状态了,就想赶紧记录下来。 学习 在学习新技术的过程中开始飘了,总感觉有了一些开发经验后就觉得什么都不用记,知道思路就行遇到了现场百…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...