《dp补卡——买卖股票问题》

目录

  • 121. 买卖股票的最佳时机
    • 贪心
    • dp思路
    • 滚动数组优化
  • 122. 买卖股票的最佳时机 II
  • 123. 买卖股票的最佳时机 III
  • 188. 买卖股票的最佳时机 IV
  • 309. 最佳买卖股票时机含冷冻期
  • 714. 买卖股票的最佳时机含手续费

121. 买卖股票的最佳时机

贪心

取最左最小值,取最右最大值,差值为最大利润

class Solution {
public:int maxProfit(vector<int>& prices) {int n = prices.size();int minprice = prices[0];int maxpro = 0;for(int i = 1; i < n; i++){minprice = min(prices[i],minprice);maxpro = max(prices[i]-minprice,maxpro);}return maxpro;}
};

dp思路

step1:dp[i][0]表示第i天持有股票最大所得现金。本题中只能买卖一次,所以买入后金额为-price[i]
dp[i][1]表示第i天不持有股票最大所得现金。持有不等同于买入。
step2:
如果第i天持有股票dp[i][0]可以由两个状态得到。
case1:第i-1持有股票,保持现状,dp[i][0] = dp[i-1][0]
case2:第i天买入股票,所得现金就是买入今天的股票后所得现金。即dp[i][0] = -price[i]
dp[i][0] = max(dp[i-1][0],-price[i]);
如果第i天不持有股票dp[i][1]可以由两个状态得到。
case1: 第i-1不持有股票,保持现状,dp[i][1] = dp[i-1][1]
case2: 第i-1持有股票,第i天卖出,dp[i][1] = dp[i-1][0] + price[i]
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+price[i])
step3:
初始状态为dp[0][0]:第0天持有股票的金额 = -prices[0]
dp[0][1]第0天不持有股票的金额 = 0;
最终结果dp[n][1]而不是dp[n][0],是因为最终必须要把股票卖出才能有收益。不卖出一定更亏。

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

滚动数组优化

由于只用到了dp[i] 与dp[i-1]两个状态,所以只需一个2 * 2的数组即可。

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

122. 买卖股票的最佳时机 II

dp[i][0]:第i天持有股票获取的最大现金
dp[i][1]:第i天不持有股票所得的最多现金
如果第i天持有股票,则dp[i][0]可以由两个状态推导;
case1:第i-1天就持有股票,保持现状,则dp[i][0] = dp[i-1][0]
case2:第i天买入股票,现金则为昨天不持有股票所得现金减去今天股票价格dp[i][0] = dp[i-1][1] - prices[i]
如果第i天不持有股票,则dp[i][1]可以由两个状态推导;
case1:第i-1天不持有股票,保持现状,dp[i][1] = dp[i-1][1]
case2:第i-1天持有股票,第i天卖出,dp[i][1] = dp[i-1][0] + prices[i]

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

123. 买卖股票的最佳时机 III

至多买卖两次,即可以买卖一次,也可以买卖两次,也可以不买卖。
每一天由五个状态:
0、没有操作
1、第一次买入
2、第一次卖出
3、第二次买入
4、第二次卖出
dp[i][j]:i表示第i天,j为[0-4]五个状态,dp[i][j]表示第i天状态j所剩最大现金。

2、确定递推公式
举例dp[i][1]:表示第i天,买入股票的状态,并不是说一定要第i天买入股票。
达到dp[i][1]状态,有两个具体操作:
case1:第i天买入股票,那么dp[i][1] = dp[i-1][0] - prices[i]
case2:第i天没有操作,那么dp[i][1] = dp[i-1][1]
dp[i-1][1] = max(dp[i-1][0]-prices[i],dp[i-1][1]);
同理dp[i][2]也有两个操作:
case1:第i天卖出股票了,那么dp[i][2] = dp[i-1][1] + prices[i]
case2:第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]也有两个操作:
case1:第i天买入股票,dp[i][3] = dp[i-1][2] - prices[i]
case2:第i天没有操作,沿用前一天买入股票的状态,即:dp[i][3] = dp[i-1][3]
同理dp[i][4]也有两个操作:
case1:第i天卖出股票,dp[i][4] = dp[i-1][3] + prices[i]
case2:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][4] = dp[i-1][4]
那么如何初始化呢?
第0天没有操作的话,dp[0][0] = 0
第0天做第一次买入操作的话,dp[0][1] = -prices[0]
第0天做第一次卖出的操作,这个初始值为0。
第0天第二次买入,不管几次,手头上没有钱,只能减少dp[0][3] = -prices[0]
第0天第二次卖出,dp[0][4] = 0

class Solution {
public:int maxProfit(vector<int>& prices) {int n = prices.size();vector<vector<int>> dp(n,vector<int>(5,0));//dp[0][0] = 0;dp[0][1] = -prices[0];//dp[0][2] = 0;dp[0][3] = -prices[0];//dp[0][4] = 0;for(int i = 1; i < n; 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[n-1][4];}
};

188. 买卖股票的最佳时机 IV

step1:
这一题为上一题的进阶版本,定义二维dp数组。
使用二维数组dp[i][j]:第i天的状态为j,所剩下的最大现金是dp[i][j]
j的状态表示为:
0不操作、1第一次买入、2第一次卖出、…
除了0以外,偶数就是卖出,奇数就是买入。因为是最多有k笔交易,所以j的范围就定义为2*k+1.

vector<vector<int>> dp(prices.size(),vector<int>(2*k+1,0));

step2:

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

step3:
初始化,只要是买入操作,现金就会相应减少,卖出操作初值均为0

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

AC代码:

class Solution {
public:int maxProfit(int k, vector<int>& prices) {int n = prices.size();if(n == 0 || k == 0) return 0; vector<vector<int>> dp(n,vector<int>(k*2+1,0));for(int i = 1; i <= 2*k; i += 2)dp[0][i] = -prices[0];for(int i = 1; i < n; i++){for(int j = 0; j <= 2 * k - 2; 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[n-1][2*k];}
};

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

状态一:买入股票状态(可能是今天买入的,也有可能是之前就买入了然后没有操作)
对于卖出股票状态,有两种:
状态二:两天前就卖出了股票,度过了冷冻期,然后一直没有操作,今天仍然保持卖出股票状态
状态三:今天卖出了股票
状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天
递推公式如下:
到达买入股票状态(状态一)即dp[i][0],有两个具体操作:
case1:前一天就是这个状态,今天沿用该状态dp[i][0] = dp[i-1][0]
case2:今天买入,有两种情况(状态四)
前一天是冷冻期,前一天是保持卖出股票的状态(状态二),这两个情况今天都有可能买入
即:dp[i][0] = max(dp[i-1][0],max(dp[i-1][3],dp[i-1][1])-prices[i])
到达保持卖出状态(状态二)即:dp[i][1],有两个具体操作:
case1:前一天就是状态二,沿用该状态
case2:前一天是冷冻期(状态四)
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]
综上的递推代码为:

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

关于dp数组的初始化:
状态一,持有股票,那么dp[0][0] = -prices[0]
状态二,保持卖出状态,dp[0][1] = 0
状态三,刚卖出股票,同样不会有收入dp[0][2] = 0
状态四,冷冻期,dp[0][3] = 0
最后的结果是从状态二到状态四中选取最大值。

class Solution {
public:int maxProfit(vector<int>& prices) {int n = prices.size();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][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[n-1][1],max(dp[n-1][2],dp[n-1][3]));}
};

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

与122. 买卖股票的最佳时机 II相比,多减去操作费用。

class Solution {
public:int maxProfit(vector<int>& prices, int fee) {int n = prices.size();vector<vector<int>> dp(2,vector<int>(2,0));dp[0][0] = -prices[0];dp[0][1] = 0;for(int i = 1; i < n; i++){//当天持有dp[i%2][0] = max(dp[(i-1)%2][0],dp[(i-1)%2][1]-prices[i]);//当天不持有dp[i%2][1] = max(dp[(i-1)%2][1],dp[(i-1)%2][0]+prices[i]-fee);}return dp[(n-1)%2][1];}
};

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

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

相关文章

oo0ooo0ooo0oo_OoO的完整形式是什么?

oo0ooo0ooo0ooOoO&#xff1a;外出 (OoO: Out of Office) OoO is an abbreviation of "Out of Office". OoO是“不在办公室”的缩写。 It is an expression, which is commonly used in the Gmail platform. It is written in the body or the subject of the email…

SP2010开发和VS2010专家食谱--第三章节--高级工作流(2)--为沙盒解决方案创建自定义活动...

尽管沙河解决方案功能有限&#xff0c;你仍然可以开发自定义活动&#xff0c;在SharePoint Designer中使用而不用改变web.config或添加.ACTION文件到根文件夹。 转载于:https://www.cnblogs.com/crazygolf/p/3856795.html

sql where 1=1和 0=1 的作用

where 11; 这个条件始终为True&#xff0c;在不定数量查询条件情况下&#xff0c;11可以很方便的规范语句。 一、不用where 11 在多条件查询中的困扰 举个例子&#xff0c;如果您做查询页面&#xff0c;并且&#xff0c;可查询的选项有多个&#xff0c;同时&#xff0c;还让用户…

j@2ff4f00f_J4F的完整形式是什么?

j2ff4f00fJ4F&#xff1a;只是为了好玩 (J4F: Just For Fun) J4F is an abbreviation of "Just For Fun". J4F是“ Just For Fun”的缩写 。 It is an expression, which is commonly used in messaging or chatting on social media networking sites like Faceboo…

《dp补卡——子序列问题》

目录300. 最长递增子序列674. 最长连续递增序列718. 最长重复子数组1143. 最长公共子序列53. 最大子序和392. 判断子序列115. 不同的子序列583. 两个字符串的删除操作72. 编辑距离647. 回文子串 &#xff08;与 5.最长回文子串思路差不多&#xff09;516. 最长回文子序列300. 最…

[LeetCode] Maximal Rectangle

Given a 2D binary matrix filled with 0s and 1s, find the largest rectangle containing all ones and return its area. 在做 Largest Rectangle in Histogram的时候有人说可以用在这题&#xff0c;看了一下还真是&#xff0c;以每行为x轴&#xff0c;每列往上累计的连续的…

什么是alpha测试_什么是ALPHA?

什么是alpha测试Α (ALPHA) Alpha is the first and foremost letter of the Greek alphabet. In the classification of Greek numerals or numbers, it constitutes a value of 1. Alpha是希腊字母的第一个也是最重要的字母 。 在希腊数字或希腊数字的分类中&#xff0c;它的…

《leetcode : 647. 回文子串 思考分析双指针解法》

647. 回文子串 如何确定是回文串&#xff1a; 找中心然后往两边扩散&#xff0c;判断是否对称即可。 在遍历中心点的时候&#xff0c;注意中心点可以是一个元素也可以是两个元素。 class Solution { public:int cal_two_extend(const string& s,int i,int j,int n){int re…

天草初级班(3)

算术运算指令算术运算指令是反映CPU计算能力的一组指令&#xff0c;也是编程时经常使用的一组指令。它包括&#xff1a;加、减、乘、除及其相关的辅助指令。 该组指令的操作数可以是8位、16位和32位(80386)。当存储单元是该类指令的操作数时&#xff0c;该操作数的寻址方式可以…

4.3.3版本之引擎bug

bug描述&#xff1a;   IOS设备上&#xff0c;当使用WWW www WWW.LoadFromCacheOrDownload(url, verNum); 下载资源时&#xff0c;第一次下载某个资源&#xff0c;www.assetBundle必定为空。 解决办法&#xff1a;   引擎版本降到4.3.2或者升到4.3.4或更高。 这个bug绝对是…

sml完整形式_411的完整形式是什么?

sml完整形式411&#xff1a;信息 (411: Information) 411 is an abbreviation of “Information". 411是“信息”的缩写 。 It is an expression, which is commonly used in messaging or chatting on social media networking sites like Facebook, Yahoo Messenger, a…

php 检测用户是否关闭浏览器

1、例子1 echo str_repeat(" ",3000);ignore_user_abort(true); mylog(online);while (true) {/** 1、程序正常结束 connection_status 0* 2、点击浏览器“停止”按钮 connection_status 1* 3、超时 connection_status 2*/echo "test<br>\n&qu…

explain用法

explain用法 EXPLAIN SELECT …… 变体&#xff1a; 1. EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句&#xff0c;运行SHOW WARNINGS 可得到被MySQL优化器优化后的查询语句 2. EXPLAIN PARTITIONS SELECT …… 用于分区表的EXPLAIN 执行计划包含的信息 id…

《位运算技巧以及Leetcode的一些位运算题目》

目录技巧练习位运算[461. 汉明距离](https://leetcode-cn.com/problems/hamming-distance/)[190. 颠倒二进制位](https://leetcode-cn.com/problems/reverse-bits/)[136. 只出现一次的数字](https://leetcode-cn.com/problems/single-number/)[260. 只出现一次的数字 III](http…

linux读取配置文件(C语言版)

一个通用的linux系统中C语言版读取配置文件的函数。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <errno.h>#define KEYVALLEN 100/* 删除左边的空格 */ char * l_trim(char * szOutput, con…

java 范围搜寻要怎么弄_搜索范围

java 范围搜寻要怎么弄Problem statement: 问题陈述&#xff1a; Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value. 给定一个以升序排列的整数nums数组&#xff0c;请找到给定目标值的开始和结束…

boa + ajax + cgi ajax请求cgi

最近公司要做一个通讯管理机,然后需要和另外一个同事一起做,我们需要用到boaAjaxCGI,以前没试过与CGI交互,一开始发现问题挺大的,用ajax请求cgi,总是不返回数据,又或者请求回来的是cgi的源码,后来发现,通过本地IIS或者直接打开html页面请求的,返回来的都是cgi的源码或者返回失败…

《DBNotes:single_table访问方法、MRR多范围读取优化、索引合并》

目录single_table访问方法constrefref_or_nullrangeindexallMRR多范围读取优化索引合并intersectionunionsort-unionsingle_table访问方法 const 在主键列或者unique二级索引与一个常数进行等值比较时才有效。 如果主键或者unique二级索引的索引列由多个列构成&#xff0c;则…

怎样通过命令管理Windows7桌面防火墙

&#xff08;1&#xff09;启用桌面防火墙netsh advfirewall set allprofiles state on&#xff08;2&#xff09;设置默认输入和输出策略netsh advfirewall set allprofiles firewallpolicy allowinbound,allowoutbound以上是设置为允许&#xff0c;如果设置为拒绝使用blockin…

ruby推送示例_Ruby for循环示例

ruby推送示例for循环 (The for loop) In programming, for loop is a kind of iteration statement which allows the block to be iterated repeatedly as long as the specified condition is not met or a specific number of times that the programmer knows beforehand. …