训练营第三十八天 | 309.最佳买卖股票时机含冷冻期动态规划系列七总结714.买卖股票的最佳时机含手续费股票问题总结篇!

309.最佳买卖股票时机含冷冻期

力扣题目链接(opens new window)

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

示例:

  • 输入: [1,2,3,0,2]
  • 输出: 3
  • 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

思路

相对于动态规划:122.买卖股票的最佳时机II (opens new window),本题加上了一个冷冻期。所以在上一题的基础上多加一个冷冻期的状态即可。

class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();vector<int> buy(len, INT_MIN);vector<int> sell(len, 0);vector<int> frozen(len, 0);buy[0] = -prices[0]; // 初始买入状态的收益sell[0] = 0;         // 初始卖出状态的收益frozen[0] = 0;        // 初始冷冻期的收益for (int i = 1; i < len; i++) {buy[i] = max(buy[i - 1], frozen[i - 1] - prices[i]); // 买入状态sell[i] = max(sell[i - 1], buy[i - 1] + prices[i]); // 卖出状态frozen[i] = max(frozen[i - 1], sell[i - 1]);          // 冷冻期状态}return max(sell[len - 1], frozen[len - 1]); // 最后的最大收益应从卖出和冷冻期中选}
};

动规五部曲:

  1. 确定dp数组以及下标的含义

dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。

其实本题很多同学搞的比较懵,是因为出现冷冻期之后,状态其实是比较复杂度,例如今天买入股票、今天卖出股票、今天是冷冻期,都是不能操作股票的。

具体可以区分出如下四个状态:

  • 状态一:持有股票状态(今天买入股票,或者是之前就买入了股票然后没有操作,一直持有)
  • 不持有股票状态,这里就有两种卖出股票状态
    • 状态二:保持卖出股票的状态(两天前就卖出了股票,度过一天冷冻期。或者是前一天就是卖出股票状态,一直没操作)
    • 状态三:今天卖出股票
  • 状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天!

j的状态为:

  • 0:状态一
  • 1:状态二
  • 2:状态三
  • 3:状态四
  1. 确定递推公式

达到买入股票状态(状态一)即:dp[i][0],有两个具体操作:

  • 操作一:前一天就是持有股票状态(状态一),dp[i][0] = dp[i - 1][0]
  • 操作二:今天买入了,有两种情况
    • 前一天是冷冻期(状态四),dp[i - 1][3] - prices[i]
    • 前一天是保持卖出股票的状态(状态二),dp[i - 1][1] - prices[i]

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

达到保持卖出股票状态(状态二)即:dp[i][1],有两个具体操作:

  • 操作一:前一天就是状态二
  • 操作二:前一天是冷冻期(状态四)

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

达到今天就卖出股票状态(状态三),即:dp[i][2] ,只有一个操作:

昨天一定是持有股票状态(状态一),今天卖出

即:dp[i][2] = dp[i - 1][0] + prices[i];

达到冷冻期状态(状态四),即:dp[i][3],只有一个操作:

昨天卖出了股票(状态三)

dp[i][3] = dp[i - 1][2];

综上分析,递推代码如下:

dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
dp[i][2] = dp[i - 1][0] + prices[i];
dp[i][3] = dp[i - 1][2];
  1. dp数组如何初始化

这里主要讨论一下第0天如何初始化。

如果是持有股票状态(状态一)那么:dp[0][0] = -prices[0],一定是当天买入股票。

保持卖出股票状态(状态二),这里其实从 「状态二」的定义来说 ,很难明确应该初始多少,这种情况我们就看递推公式需要我们给他初始成什么数值。

如果i为1,第1天买入股票,那么递归公式中需要计算 dp[i - 1][1] - prices[i] ,即 dp[0][1] - prices[1],那么大家感受一下 dp[0][1] (即第0天的状态二)应该初始成多少,只能初始为0。想一想如果初始为其他数值,是我们第1天买入股票后 手里还剩的现金数量是不是就不对了。

今天卖出了股票(状态三),同上分析,dp[0][2]初始化为0,dp[0][3]也初始为0。

  1. 确定遍历顺序

从递归公式上可以看出,dp[i] 依赖于 dp[i-1],所以是从前向后遍历。

最后结果是取 状态二,状态三,和状态四的最大值,不少同学会把状态四忘了,状态四是冷冻期,最后一天如果是冷冻期也可能是最大值。

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

动态规划系列七总结

动态规划:买卖股票的最佳时机II (opens new window)中股票可以买卖多次了!

这也是和121. 买卖股票的最佳时机 (opens new window)的唯一区别(注意只有一只股票,所以再次购买前要出售掉之前的股票)

重点在于递推公式的不同。

dp数组的含义:

  • dp[i][0] 表示第i天持有股票所得现金。
  • dp[i][1] 表示第i天不持有股票所得最多现金

递推公式:

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]);

本题和121. 买卖股票的最佳时机 (opens new window)的代码几乎一样,唯一的区别在:

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

动态规划:买卖股票的最佳时机IV (opens new window)最多可以完成 k 笔交易。

相对于上一道动态规划:123.买卖股票的最佳时机III (opens new window),本题需要通过前两次的交易,来类比前k次的交易

  1. 确定dp数组以及下标的含义

使用二维数组 dp[i][j] :第i天的状态为j,所剩下的最大现金是dp[i][j]

j的状态表示为:

  • 0 表示不操作
  • 1 第一次买入
  • 2 第一次卖出
  • 3 第二次买入
  • 4 第二次卖出
  • .....

除了0以外,偶数就是卖出,奇数就是买入

  1. 确定递推公式

dp[i][1],表示的是第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]);
}

动态规划:123.买卖股票的最佳时机III (opens new window)最大的区别就是这里要类比j为奇数是买,偶数是卖的状态

  1. dp数组如何初始化

dp[0][j]当j为奇数的时候都初始化为 -prices[0]

代码如下:

for (int j = 1; j < 2 * k; j += 2) {dp[0][j] = -prices[0];
}

在初始化的地方同样要类比j为奇数是买、偶数是卖的状态

  1. 确定遍历顺序

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

最后一次卖出,一定是利润最大的,dp[prices.size() - 1][2 * k]即红色部分就是最后求解。

动态规划:最佳买卖股票时机含冷冻期 (opens new window)尽可能地完成更多的交易(多次买卖一支股票),但有冷冻期,冷冻期为1天

相对于动态规划:122.买卖股票的最佳时机II (opens new window),本题加上了一个冷冻期

本题则需要第三个状态:不持有股票(冷冻期)的最多现金

714.买卖股票的最佳时机含手续费

力扣题目链接(opens new window)

给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

示例 1:

  • 输入: prices = [1, 3, 2, 8, 4, 9], fee = 2
  • 输出: 8

解释: 能够达到的最大利润:

  • 在此处买入 prices[0] = 1
  • 在此处卖出 prices[3] = 8
  • 在此处买入 prices[4] = 4
  • 在此处卖出 prices[5] = 9
  • 总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

注意:

  • 0 < prices.length <= 50000.
  • 0 < prices[i] < 50000.
  • 0 <= fee < 50000.

思路

本题贪心解法:贪心算法:买卖股票的最佳时机含手续费(opens new window)

相对于动态规划:122.买卖股票的最佳时机II (opens new window),本题只需要在计算卖出操作的时候减去手续费就可以了,代码几乎是一样的。

唯一差别在于递推公式部分.

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

股票问题总结篇!

股票问题总结

  • 动态规划:121.买卖股票的最佳时机(opens new window)
  • 动态规划:122.买卖股票的最佳时机II(opens new window)
  • 动态规划:123.买卖股票的最佳时机III(opens new window)
  • 动态规划:188.买卖股票的最佳时机IV(opens new window)
  • 动态规划:309.最佳买卖股票时机含冷冻期(opens new window)
  • 动态规划:714.买卖股票的最佳时机含手续费(opens new window)

#卖股票的最佳时机

动态规划:121.买卖股票的最佳时机 (opens new window),股票只能买卖一次,问最大利润

// 版本一
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];}
};

#买卖股票的最佳时机II

动态规划:122.买卖股票的最佳时机II (opens new window)可以多次买卖股票,问最大收益。

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

#买卖股票的最佳时机III

动态规划:123.买卖股票的最佳时机III (opens new window)最多买卖两次,问最大收益。

// 版本二
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];}
};

#买卖股票的最佳时机IV

动态规划:188.买卖股票的最佳时机IV (opens new window)最多买卖k笔交易,问最大收益。

class Solution {
public:int maxProfit(int k, vector<int>& prices) {       vector<int> buy(k, INT_MIN);vector<int> sell(k, 0);    for(int price : prices) {buy[0] = max(buy[0], -price);sell[0] = max(sell[0], buy[0] + price);   for (int i = 1; i < k; i++) {buy[i] = max(buy[i], sell[i - 1] - price);sell[i] = max(sell[i], buy[i] + price);}}return sell[k - 1];}
};

#最佳买卖股票时机含冷冻期

动态规划:309.最佳买卖股票时机含冷冻期 (opens new window)可以多次买卖但每次卖出有冷冻期1天。

相对于动态规划:122.买卖股票的最佳时机II (opens new window),本题加上了一个冷冻期。

class Solution {
public:int maxProfit(vector<int>& prices) {int len = prices.size();vector<int> buy(len, INT_MIN);vector<int> sell(len, 0);vector<int> frozen(len, 0);buy[0] = -prices[0]; // 初始买入状态的收益sell[0] = 0;         // 初始卖出状态的收益frozen[0] = 0;        // 初始冷冻期的收益for (int i = 1; i < len; i++) {buy[i] = max(buy[i - 1], frozen[i - 1] - prices[i]); // 买入状态sell[i] = max(sell[i - 1], buy[i - 1] + prices[i]); // 卖出状态frozen[i] = max(frozen[i - 1], sell[i - 1]);          // 冷冻期状态}return max(sell[len - 1], frozen[len - 1]); // 最后的最大收益应从卖出和冷冻期中选}
};

#买卖股票的最佳时机含手续费

动态规划:714.买卖股票的最佳时机含手续费 (opens new window)可以多次买卖,但每次有手续费。

相对于动态规划:122.买卖股票的最佳时机II (opens new window),本题只需要在计算卖出操作的时候减去手续费就可以了,代码几乎是一样的。

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Navicat和SQLynx产品功能比较一(整体比较)

Navicat和SQLynx都是数据库管理工具&#xff0c;在过去的二十年中&#xff0c;国内用户主要是使用Navicat偏多&#xff0c;一般是个人简单开发需要&#xff0c;数据量一般不大&#xff0c;开发相对简单。SQLynx是最近几年的数据库管理工具&#xff0c;Web开发&#xff0c;桌面版…

Ollama在MacOS、Linux本地部署千问大模型及实现WEB UI访问

一、前言 阿里通义千问发布了Qwen2&#xff0c;提供了0.5B&#xff5e;72B的量级模型&#xff0c;在​​Ollama官网​​可以搜索qwen2查看&#xff0c;本文提供了Ollama的下载&#xff08;在线/离线安装&#xff09;、Ollama运行模型、使用WebUI连接模型以及页面简单配置。 …

计算机网络(4) 最长前缀匹配(路由转发表)

一.路由转发 网络数据包IP段只包含源地址与目的地址&#xff0c;经过数据链路层包装与物理层信号形式转换&#xff0c;最终经由不同的链路节点到达目的地址。这个过程是一步一步&#xff08;hop by hop&#xff09;进行的&#xff0c;路过一个路由节点则称为一跳。每个路由节点…

Java中ArrayList(顺序表)的自我实现(如果想知道Java中怎么自我实现ArrayList,那么只看这一篇就足够了!)

前言&#xff1a;在 Java 编程中&#xff0c;ArrayList 是一种非常常用的数据结构&#xff0c;它提供了动态数组的实现方式&#xff0c;可以方便地存储和操作数据。相比于传统的数组&#xff0c;ArrayList 具有更多的灵活性和便利性&#xff0c;可以根据需要动态地调整大小&…

温泉镇旅游微信小程序的设计与实现(论文+源码)_kaic

摘要 旅游业随着经济的快速发展呈现出一派欣欣向荣的景象&#xff0c;尤其是近两年来&#xff0c;各个行业运用科技以及因特网来促进旅游迅速发展&#xff0c;逐渐都显示出了的问题&#xff0c;特别突出的是在线上推广&#xff0c;其缺点也是特别明显。尽管在新冠肺炎的冲击下&…

后端中缓存的作用以及基于Spring框架演示实现缓存

缓存的作用及演示 现在我们使用的程序都是通过去数据库里拿数据然后展示的 长期对数据库进行数据访问 这样数据库的压力会越来越大 数据库扛不住了 创建了一个新的区域 程序访问去缓存 缓存区数据库 缓存里放数据 有效降低数据访问的压力 我们首先进行一个演示 为了演示…

基于System-Verilog的FPGA设计与仿真

一、System-Verilog System Verilog的发展 SystemVerilog 的出现是为了因应日益复杂的数位电路设计和验证需求。虽然Verilog HDL 在早期的数位电路设计中得到了广泛应用&#xff0c;但随着技术的发展和电路复杂度的增加&#xff0c;Verilog HDL 在某些方面已经显得有些不足以满…

甘肃这款饼子很火 你是否有吃过呢

白吉饼那独特的外形&#xff0c;圆圆的十分可爱。&#x1f44f;它的表皮酥脆&#xff0c;内里绵软&#xff0c;麦香四溢。&#x1f60b;拿在手里沉甸甸的&#xff0c;就知道用料十足。 无论是直接吃&#xff0c;感受那纯粹的面香&#xff0c;还是夹上腊汁肉&#xff0c;变成美味…

智慧监狱技术解决方案

1. **建设背景**&#xff1a;介绍了智慧监狱建设的战略部署&#xff0c;包括司法部提出的“数字法治、智慧司法”信息化体系建设&#xff0c;以及智慧监狱建设的总体目标、重点任务和实施步骤。 2. **建设需求**&#xff1a;分析了当前监狱系统存在的问题&#xff0c;如子系统…

Python 小市值股票模型代码及回测分析

目录 一、模型介绍 二、代码详解 2.1 初始化函数 2.2 股票筛选过滤函数 2.3 止损函数 2.4 开盘时运行函数 2.5 调仓函数 三、回测结果分析 3.1 收益净值图与概述 3.2 模型收益概览 3.3 年度收益图 3.4 月度收益的时间序列 3.5 月度收益热力图 3.6 月度收益频次分…

手机上安装AI模型是一种什么体验?

昨天参加微软的AI DAY活动&#xff0c;看到微软的技术大佬分享了一个场景&#xff0c;就是坐飞机从上海到北京&#xff0c;机长广播因为天气原因&#xff0c;飞机需要盲降&#xff0c;他说当时听到盲降第一反应感觉有点恐慌&#xff0c;但是因为飞机上受限于网络环境&#xff0…

玄机平台应急响应—MySQL应急

前言 这个是比较简单的&#xff0c;其实和MySQL没啥太大的关系&#xff0c;没涉及太多MySQL的知识。看一下它的flag要求吧。 flag1 它说黑客写入的shell&#xff0c;那我们就去它的网站目录去看看&#xff0c;果然有一个叫sh.php的文件。 flag1{ccfda79e-7aa1-4275-bc26-a61…

C++ 18 之 函数的重载

c18函数的重载.cpp #include <iostream> #include <string.h> using namespace std;void fun4(int a) {cout << "int a: "<< a << endl; } void fun4(double a) {cout << "double a: " << a << endl; }v…

图书管理系统(SpringBoot+SpringMVC+MyBatis)

目录 1.数据库表设计 2.引入MyBatis和MySQL驱动依赖 3.配置数据库&日志 4.Model创建 5.用户登录功能实现 6.实现添加图书功能 7.实现翻页功能 1.数据库表设计 数据库表是应⽤程序开发中的⼀个重要环节, 数据库表的设计往往会决定我们的应⽤需求是否能顺利实现, 甚至决…

挑战5分钟内基于Springboot+SpringMVC+Mybatis-plus快速构建web后端三层架构

目标 在清晨的代码编辑器上&#xff0c;一场新的挑战即将开始。程序员们肃立于安静的办公室&#xff0c;眼神专注地盯着屏幕&#xff0c;等待着编译器的一声提示。 随着编译器输出的激动人心的"start!"的提示&#xff0c;战斗的序幕拉开了。Bug如潮水般涌来&#x…

SAP Build 2-PDF数据提取与决策

0. 安装desktop agent 在后续过程中发现要预先安装desktop agent&#xff0c;否则没法运行自动化流程… 0.1 agent下载 参考官方文档说明 https://help.sap.com/docs/build-process-automation/sap-build-process-automation/create-user-in-rbsc-download-repository?loca…

什么是无头浏览器以及其工作原理?

如果您对这个概念还不熟悉&#xff0c;那么使用无头网络浏览器的想法可能会让您感到不知所措。无头浏览器本质上与您熟悉的网络浏览器相同&#xff0c;但有一个关键区别&#xff1a;它们没有图形用户界面 (GUI)。这意味着没有按钮、选项卡、地址栏或视觉显示。 相反&#xff0c…

极致深耕,打造核心竞争壁垒——探寻蓝思科技穿越周期的密码

作者 | 曾响铃 文 | 响铃说 一家企业&#xff0c;如何才能在时代变幻的风云中不计较一时得失&#xff0c;长期稳健发展&#xff0c;穿越周期&#xff1f;本期主题就来探寻一家在湖南的国际化企业的发展密码。 穿越周期的企业&#xff0c;都在坚持一个驱动发展的“原点” 细…

Python虚拟环境的配置

前言&#xff1a; 本人一度被Python的虚拟环境的配置所困扰&#xff0c;前段时间抽空学习了一下&#xff0c;现在总结一下方法&#xff0c;供大家参考。 先使用winr打开命令行窗口。 展示所有虚拟环境 conda env list 创建虚拟环境 例如我们创建一个叫做py_sk的虚拟环境 …

Windows下的zip压缩包版Mysql8.3.0数据迁移到Mysql8.4.0可以用拷贝data文件夹的方式

Windows下的zip压缩包版Mysql8.3.0数据迁移到Mysql8.4.0可以用拷贝data文件夹的方式 拷贝后, 所有账户和数据都是一样的 步骤 停止MySQL服务 net stop mysql 或 sc.exe stop mysql net stop mysqlsc.exe stop mysql卸载 Mysql8.3.0 的服务 mysqld remove 或 mysqld remove m…