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

本文主要是介绍第五十一天| 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数组含义 以及 考虑全各种状态之间的转换情况 来确定递推公式。

这篇关于第五十一天| 309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Java Stream 的 Collectors.toMap高级应用与最佳实践

《JavaStream的Collectors.toMap高级应用与最佳实践》文章讲解JavaStreamAPI中Collectors.toMap的使用,涵盖基础语法、键冲突处理、自定义Map... 目录一、基础用法回顾二、处理键冲突三、自定义 Map 实现类型四、处理 null 值五、复杂值类型转换六、处理

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

MyBatis-Plus 自动赋值实体字段最佳实践指南

《MyBatis-Plus自动赋值实体字段最佳实践指南》MyBatis-Plus通过@TableField注解与填充策略,实现时间戳、用户信息、逻辑删除等字段的自动填充,减少手动赋值,提升开发效率与... 目录1. MyBATis-Plus 自动赋值概述1.1 适用场景1.2 自动填充的原理1.3 填充策略

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.