代码随想录训练营 Day41打卡 动态规划 part08 121. 买卖股票的最佳时机 122. 买卖股票的最佳时机II 123. 买卖股票的最佳时机III

本文主要是介绍代码随想录训练营 Day41打卡 动态规划 part08 121. 买卖股票的最佳时机 122. 买卖股票的最佳时机II 123. 买卖股票的最佳时机III,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

代码随想录训练营 Day41打卡 动态规划 part08

一、力扣121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

在这个问题中,我们需要计算在给定的股票价格数组 prices 中,最多只能进行一次交易(即一次买入和一次卖出)的情况下,能够获得的最大利润。为了实现这一点,我们使用动态规划的方法来模拟整个买卖过程。

我们定义两个状态:

  • dp[i][0] 表示第 i 天持有股票时能够获得的最大现金金额。
  • dp[i][1] 表示第 i 天不持有股票时能够获得的最大现金金额。

注意,“持有股票”不一定表示当天买入股票,也可能是之前买入的,并且持续持有到当天。同样地,“不持有股票”可以是当天卖出股票,或者之前已经卖出并且保持不持有状态。

持有股票时 (dp[i][0]):

如果第 i-1 天已经持有股票,那么保持现状:dp[i - 1][0]。
如果第 i 天买入股票,那么所得现金为 -prices[i]。
公式:dp[i][0] = max(dp[i - 1][0], -prices[i])

不持有股票时 (dp[i][1]):

如果第 i-1 天已经不持有股票,那么保持现状:dp[i - 1][1]。
如果第 i 天卖出股票,那么所得现金为 prices[i] + dp[i - 1][0]。
公式:dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0])
以示例输入:[7,1,5,3,6,4]为例,dp数组状态如下:
在这里插入图片描述
dp[5][1]就是最终结果。

为什么不是dp[5][0]呢?

因为本题中不持有股票状态所得金钱一定比持有股票状态得到的多!

代码实现

class Solution:def maxProfit(self, prices: List[int]) -> int:length = len(prices)if length == 0:return 0# 初始化 dp 数组,大小为 [length][2]# dp[i][0] 表示第 i 天持有股票时的最大现金# dp[i][1] 表示第 i 天不持有股票时的最大现金dp = [[0] * 2 for _ in range(length)]# 初始化第一天的状态dp[0][0] = -prices[0]  # 第 0 天买入股票dp[0][1] = 0  # 第 0 天不持有股票# 动态规划,计算每一天的状态for i in range(1, length):# 第 i 天持有股票的最大现金dp[i][0] = max(dp[i - 1][0], -prices[i])# 第 i 天不持有股票的最大现金dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0])# 最终结果是最后一天不持有股票时的最大现金return dp[-1][1]

力扣题目链接
题目文章讲解
题目视频讲解

二、力扣122. 买卖股票的最佳时机II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
示例
输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。
最大总利润为 4 + 3 = 7 。

在这个问题中,我们需要找到一个策略,使得通过多次交易(买入和卖出股票)能够获得的最大利润。与之前只能进行一次交易的情况不同,这里允许在多个不同的时间点进行多次交易,每次交易只能持有一股股票。

我们仍然使用动态规划来解决这个问题。我们定义两个状态:

dp[i][0] 表示第 i 天持有股票时能够获得的最大现金金额。
dp[i][1] 表示第 i 天不持有股票时能够获得的最大现金金额。

与只能进行一次交易不同,这里第 i 天买入股票的现金金额可以是前一天不持有股票时的现金减去今天的股票价格,即 dp[i-1][1] - prices[i]。

持有股票时 (dp[i][0]):

如果第 i-1 天已经持有股票,那么保持现状:dp[i-1][0]。
如果第 i 天买入股票,那么所得现金为前一天不持有股票的现金减去今天的股票价格:dp[i-1][1] - prices[i]。
公式:dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i])

不持有股票时 (dp[i][1]):

如果第 i-1 天已经不持有股票,那么保持现状:dp[i-1][1]。
如果第 i 天卖出股票,那么所得现金为今天的股票价格加上前一天持有股票的现金:dp[i-1][0] + prices[i]。
公式:dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])

代码实现

class Solution:def maxProfit(self, prices: List[int]) -> int:length = len(prices)# 特殊情况处理if length == 0:return 0# 初始化 dp 数组,大小为 [length][2]# dp[i][0] 表示第 i 天持有股票时的最大现金# dp[i][1] 表示第 i 天不持有股票时的最大现金dp = [[0] * 2 for _ in range(length)]# 初始化第一天的状态dp[0][0] = -prices[0]  # 第 0 天买入股票dp[0][1] = 0  # 第 0 天不持有股票# 动态规划,计算每一天的状态for i in range(1, length):# 第 i 天持有股票的最大现金dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i])# 第 i 天不持有股票的最大现金dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i])# 最终结果是最后一天不持有股票时的最大现金return dp[-1][1]

力扣题目链接
题目文章讲解
题目视频讲解

二、力扣123. 买卖股票的最佳时机III

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例
输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

在这个问题中,我们需要找到一个策略,通过最多两次交易(即最多买入两次和卖出两次)来获得最大利润。每次交易只能持有一股股票,因此有五种状态:

dp[i][0]:表示第 i 天没有任何操作或不进行任何交易时的最大利润。
dp[i][1]:表示第 i 天进行了第一次买入操作后的最大利润。
dp[i][2]:表示第 i 天进行了第一次卖出操作后的最大利润。
dp[i][3]:表示第 i 天进行了第二次买入操作后的最大利润。
dp[i][4]:表示第 i 天进行了第二次卖出操作后的最大利润。

dp[i][1]: 第 i 天持有股票(第一次买入)的最大利润:
如果第 i 天买入股票:dp[i-1][0] - prices[i]。
如果第 i 天不买入股票:dp[i-1][1]。
公式:dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])

dp[i][2]: 第 i 天不持有股票(第一次卖出)的最大利润:
如果第 i 天卖出股票:dp[i-1][1] + prices[i]。
如果第 i 天不卖出股票:dp[i-1][2]。
公式:dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])

dp[i][3]: 第 i 天持有股票(第二次买入)的最大利润:
如果第 i 天买入股票:dp[i-1][2] - prices[i]。
如果第 i 天不买入股票:dp[i-1][3]。
公式:dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])

dp[i][4]: 第 i 天不持有股票(第二次卖出)的最大利润:
如果第 i 天卖出股票:dp[i-1][3] + prices[i]。
如果第 i 天不卖出股票:dp[i-1][4]。
公式:dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i])

dp数组初始化

dp[0][0] = 0:表示第 0 天不进行任何操作,利润为 0。
dp[0][1] = -prices[0]:表示第 0 天第一次买入股票后的利润,即减去第 0 天的股票价格。
dp[0][2] = 0:表示第 0 天第一次卖出股票后的利润,因为不能卖出不存在的股票,所以利润为 0。
dp[0][3] = -prices[0]:表示第 0 天第二次买入股票后的利润,即再减去第 0 天的股票价格。
dp[0][4] = 0:表示第 0 天第二次卖出股票后的利润,同理也为 0。

代码实现

class Solution:def maxProfit(self, prices: List[int]) -> int:# 特殊情况处理,如果没有股票价格数据,返回 0if len(prices) == 0:return 0# 初始化 dp 数组,大小为 [len(prices)][5]dp = [[0] * 5 for _ in range(len(prices))]# 第 0 天的状态初始化dp[0][0] = 0  # 不操作dp[0][1] = -prices[0]  # 第一次买入dp[0][2] = 0  # 第一次卖出dp[0][3] = -prices[0]  # 第二次买入dp[0][4] = 0  # 第二次卖出# 动态规划,遍历每一天的状态for i in range(1, len(prices)):# 第 i 天不操作的状态,延续前一天的状态dp[i][0] = dp[i-1][0]# 第 i 天第一次买入股票的状态dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])# 第 i 天第一次卖出股票的状态dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])# 第 i 天第二次买入股票的状态dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])# 第 i 天第二次卖出股票的状态dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i])# 最终返回的结果是最后一天,第二次卖出股票后的最大利润return dp[-1][4]

力扣题目链接
题目文章讲解
题目视频讲解

这篇关于代码随想录训练营 Day41打卡 动态规划 part08 121. 买卖股票的最佳时机 122. 买卖股票的最佳时机II 123. 买卖股票的最佳时机III的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114864

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip