第五十一天| 309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

第四十八天| 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II-CSDN博客

第五十天| 123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV-CSDN博客

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

题目链接:309 最佳买卖股票时机含冷冻期

题干:给定一个整数数组prices,其中第  prices[i] 表示第 i 天的股票价格 。​

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

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

思考:动态规划。本题是在 122.买卖股票的最佳时机II 的基础上加上冷冻期。

  • 确定dp数组以及下标的含义(本题的难点)

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

出现冷冻期后,状态比较复杂度。尤其要注意 不进行买入卖出 的几种情况。

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

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

 以上状态j分别用0,1,2,3代指。

本题之所以要将不持有股票的状态分为状态二和状态三,是由于如果本题的冷冻期从不持有股票的状态推出,则冷冻期连续,不止一天,与题干矛盾。

  • 确定递推公式

达到买入股票状态(状态一)即: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][1]
  • 操作二:前一天是冷冻期(状态四),dp[i - 1][3]

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数组如何初始化

从递推公式可以看出,基础为dp[0][j],即第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天的利润作本金,因此初始为0。

同理第0天的今天卖出股票(状态三),dp[0][2]也应初始化为0。

此外由于冷冻期不操作,状态四和状态三的值恒等。因此dp[0][3]也初始为0。

  • 确定遍历顺序

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

  • 举例推导dp数组

以 [1,2,3,0,2] 为例,dp数组如下:

最后 获取最大金额一定不是持有股票的状态,只可能是最后一天卖出股票(状态三)或最后一天不操作(状态二和状态四),并且返回这三种状态的最大值。 

代码:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(prices.size(), vector<int>(4));
        dp[0][0] = - prices[0];
        dp[0][1] = 0;
        dp[0][2] = 0;
        dp[0][3] = 0;

        for (int i = 1; i < prices.size(); i++) {
            //保持持有股票、之前处于卖出股票本次买入股票、之前处于冷冻期本次买入股票
            dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][1], dp[i - 1][3]) - 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[prices.size() - 1][2], max(dp[prices.size() - 1][1], dp[prices.size() - 1][3]));
    }
};

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

题目链接:714 买卖股票的最佳时机含手续费

题干:给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。

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

返回获得利润的最大值。

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

思考:动态规划。本题与 122.买卖股票的最佳时机II 的区别就是这里需要多一个减去手续费的操作。减去手续费的操作既可以放在购入股票时也可以放在卖出股票时。(下面的代码将费用放在购票时)。递推公式和初始化稍加修改即可。

代码:

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        //dp[i][0]:第i天持有股票状态    dp[i][1]:第i天不持有股票状态
        vector<vector<int>> dp(prices.size(), vector<int>(2));
        dp[0][0] = - prices[0] - fee;       //买入股票时考虑手续费
        dp[0][1] = 0;

        for (int i = 1; i < prices.size(); i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i] - fee);   //一直持有股票 或 第i天买入股票(上一次交易利润作本金)
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);         //第i天卖出股票 或 之前就卖出股票
        }
        return dp[prices.size() - 1][1]; 
    }
};

股票问题总结:

股票问题的重点有两处:

        对于股票交易次数的限制 可以从 每次交易的本金 和 交易状态考虑。只需一次交易则交易本金一直为0;无限次交易则将上次交易的利润当作本次交易的本金;有限次(大于一次)交易通过添加 不同次交易状态 来同步更新 保证不超过指定交易次数。

​​​​​​​        对于交易情况的限制 可以从 交易状态考虑。本质上和有限次交易次数限制一样,但是要考虑具体的状态种类 来确定dp数组含义 以及 考虑全各种状态之间的转换情况 来确定递推公式。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue api封装

api封装 由于一个项目里api是很多的&#xff0c;随处都在调&#xff0c;如果按照之前的写法&#xff0c;在每个组件中去调api&#xff0c;一旦api有改动&#xff0c;遍地都要去改&#xff0c;所以api应该也要封装一下&#xff0c;将api的调用封装在函数中&#xff0c;将函数集…

Keepalive 解决nginx 的高可用问题

一 说明 keepalived利用 VRRP Script 技术&#xff0c;可以调用外部的辅助脚本进行资源监控&#xff0c;并根据监控的结果实现优先动态调整&#xff0c;从而实现其它应用的高可用性功能 参考配置文件&#xff1a; /usr/share/doc/keepalived/keepalived.conf.vrrp.localche…

GPT-4技术解析:与Claude3、Gemini、Sora的技术差异与优势对比

【最新增加Claude3、Gemini、Sora、GPTs讲解及AI领域中的集中大模型的最新技术】 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚…

干货分享③:免费制作产品管理系统!

他来了&#xff0c;他来了&#xff0c;他带着码上飞CodeFlying走来了&#xff01;今天继续为大家带来一期干货分享&#xff0c;教大家如何免费使用码上飞来的开发产品管理系统 &#xff01; 一、登陆官网 码上飞 CodeFlying | AI 智能软件开发平台&#xff01; 点击立即体验注…

代码随想录算法训练营Day38 || leetCode 7509. 斐波那契数 || 70. 爬楼梯 || 746. 使用最小花费爬楼梯

动态规划和我们数电中学习的时序电路类似&#xff0c;某一时刻的状态不仅与当前时刻的输入有关&#xff0c;还与之前的状态有关&#xff0c;所以推导过程中我们需要模拟题目中的情况&#xff0c;来找到每一时刻状态间的关系。 做题思路如下 509. 斐波那契数 此题简单 状态方程…

对于simplex算法的代码实现最优解存在性的证明

对于任何线性规划系统,并不是都存在最优解,如果在约束条件中,每个常量都是大于等于0的,那么线性规划系统肯定是有最优解的,此时将每个变量选取为0就可以了。而只有当约束条件中的常量有小于0的情况的时候,才需要验证系统是否存在最优解,给出一个反例,进行最优解的存在性…

[项目设计] 从零实现的高并发内存池(五)

&#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[高并发内存池] ❤️ 前置学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 ​ 目录 8 使用定长内存池脱离new 9. 释放对象时不传大小 10.性能优化 10.1…

电脑要用多少V的电源?电脑电源输入电压是市电

台式电源的输出电压是多少&#xff1f; 电脑电源输出一般有三种不同的电压&#xff0c;分别是&#xff1a; 12V、5V、3.3V。 电脑电源负责给电脑配件供电&#xff0c;如CPU、主板、内存条、硬盘、显卡等&#xff0c;是电脑的重要组成部分。 工作电流根据不同的硬件及其使用状…

前端技术研究越深入,越觉得技术不是决定录用唯一条件。

一、拒绝抬杠 我说技能不是唯一条件&#xff0c;不是说技能不重要&#xff0c;招聘前端条件是1X,其中1是技能&#xff0c;X是其他条件。 如果X条件很优秀&#xff0c;1这个条件可以降格为0.8、0.5&#xff0c;甚至更低。 有人就抬杠&#xff0c;那为啥不招聘清洁工来干前端&…

软考一年一次,自学的人扛不住了...

相信大家最近也看到了&#xff0c;软考有些科目已经改为一年一次&#xff0c;对于自学的人来讲&#xff0c;无疑是雪上加霜... 2024年软考考试时间安排&#xff1a; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 添加图片注释&#xff0c;不超过 140 字…

构建读写分离的数据库集群

目录 1. 基础环境配置 &#xff08;1&#xff09;修改主机名 &#xff08;2&#xff09;编辑hosts文件 &#xff08;3&#xff09;配置Yum安装源 &#xff08;4&#xff09;安装JDK环境 2. 部署MariaDB主从数据库集群服务 &#xff08;1&#xff09;安装MariaDB服务 &a…

记录一次Dubbo远程调用的错误

情景&#xff1a;有一个生成PDF的接口中&#xff0c;如下&#xff1a; GET Path("/getPDF") public void getPDF(QueryParam("id") String id, Context HttpServletResponse response) {………… }之前实现的代码都写在了Controller里面&#xff0c;代码里…

网络调试助手使用MQTT协议与Mosquitto通信(3)

一、连接报文 一开始设备需要连接到mqtt服务器&#xff0c;连接时的数据包内需要携带对应的设备ID&#xff0c;以及用户名和密码。这使用默认的用户名和密码。设备ID每一个设备都需要设置为不同的&#xff0c;两个相同的ID只能允许一台设备在线&#xff0c;另一个相同的ID的设备…

VUE前端问题

一、图表内容不显示 watch: {chartData3: {handler() {this.init();},},timeData3: {handler() {this.init();},},}, 添加上面代码可以动态监控数据&#xff0c;实现图表的展示。 二、背景图片报错显示不出来 解决方法&#xff1a; background: url(~/assets/login/e.png) …

hack the box 之Bizness

端口扫描 服务扫描 漏洞扫描 Web 没什么东西目录扫描一下 注意这里有301需要操作一下 这个需要登入 直接查一下这个登入的目录 【Apache OFBiz 系列】手把手教你快速运行OFBiz项目_/ofbiz/runtime/data/derby/ofbiz/seg0-CSDN博客 右下角有版本 有关apache ofbiz的漏洞信息 …

【Linux】权限管理(文件的访问者、类型和访问权限,chmod、chown、chgrp、umask,粘滞位)

目录 00.前言 01.文件访问者的分类 02.文件类型和访问权限 文件类型&#xff1a; 文件基本权限&#xff1a; 03.文件权限值的表示方法 04.访问权限的设置 &#xff08;1&#xff09;chmod &#xff08;2&#xff09;chown &#xff08;3&#xff09;chgrp &#xff0…

测试入门篇

测试: 这里写目录标题 测试:基础概念:BUG:创建一个合理的bug:bug 的级别:跟开发争执如何解决: 测试用例:编写测试用例的万能公式:案例: 登录功能的测试:设计测试用例的方法: 进阶篇(主要介绍测试方法):自动化测试:自动化测试的分类:selenium( web 自动化测试工具 )环境部署:什么…

Jvm 虚拟机命令

Jps (查看正在运行的Java 进程) jps -q 只输出进程id、省略主类名称 -m 输出Jvm 进程启动时传递给主类main 函数参数 -l 输出主类全名称 -v 输出 Jvm 启动时的Jvm 参数 Jstat 查看 Jvm 统计信息 -class 监视类装载、卸载数量、总空间以及类装载所耗费的时间 -gc 监视 Java 堆…

【力扣 - 无重复字符的最长字符串】

题目描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。 示例 2: 输入: s "bbbbb" 输出: 1 …

程序地址空间

引入 看这样一段代码 1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 5 int g_val 100;6 int main()7 {8 pid_t id fork();9 if(id0)10 {11 int cnt 0;12 while(1)13 {14 printf("child,pid:%d,ppid:%d,g_val:%d,&g_v…