[LeetCode] Best Time to Buy and Sell Stock 6道合集【DP】
1. Best Time to Buy and Sell Stock
2. Best Time to Buy and Sell Stock II
3. Best Time to Buy and Sell Stock III
4. Best Time to Buy and Sell Stock IV
5. Best Time to Buy and Sell Stock with Cooldown
6. Best Time to Buy and Sell Stock with Transaction Fee
一个一个来:
1. Best Time to Buy and Sell Stock
题意:给定股票每日的售价,求 一次买进和一次卖出最多可以获取多大利润?
思路:其实就是求买进时和卖出是最大差价。每次更新当前最小价格,dp即可。
class Solution {
public:
int maxProfit(vector<int> &prices) {
int maxPro = ;
int minPrice = INT_MAX;
for(int i = ; i < prices.size(); i++){
minPrice = min(minPrice, prices[i]);
maxPro = max(maxPro, prices[i] - minPrice);
}
return maxPro;
}
};
2. Best Time to Buy and Sell Stock II
题意:给定股票每日的售价,求若干次买卖最多可以获取多大利润?
思路:其实就是求股票低价买,高价卖最多能获得多少钱。求连续上升的高度和。
如12314为 1买进3卖出1买进4卖出。
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size()==)return ;
int ans=;
for(int i=;i<prices.size()-;i++)
if(prices[i+]>prices[i]) ans+=prices[i+]-prices[i];
return ans;
}
};
3. Best Time to Buy and Sell Stock III
题意:给定股票每日的售价,求最多两次买卖最多可以获取多大利润?
思路:DP
设dp[i][j]为到第j天第i次交易能获取的最大值。当前状态由前一时间没有交易转移而来,或者由i-1次交易j之前所有时间点买入,当前的时间点卖出完成一次交易转移
转移方程:dp[i, j] = max(dp[i, j-1], prices[i] - prices[k] + dp[i-1, k-1]), k=[0..j-1] k的循环可以简化
Time complexity is O(kn), space complexity is O(kn).
class Solution {
public:
int maxProfit(vector<int> & prices)
{
if(prices.size()<=)
return ;
else{
int K=;
vector<vector<int>> dp(K+,vector<int>(prices.size(),));
for(int i=;i<=K;i++)
{
int tmpMax = -prices[];
for(int j=;j<prices.size();j++)
{
tmpMax=max(tmpMax,dp[i-][j-]-prices[j-]); // k那一步的循环简化,注意这里实际是算的dp[i-1][j-2], 因为dp[i-1][j-1]同时买卖相当于没交易
dp[i][j]=max(dp[i][j-],prices[j]+tmpMax);
}
}
return dp[][prices.size()-];
}
}
};
4. Best Time to Buy and Sell Stock IV
题意:给定股票每日的售价,求最多k次买卖最多可以获取多大利润?
思路:同III的2次交易,换成K后直接做可能超时,考虑当k最多为n/2, 当k>=n/2时相当于无穷次,即Best Time to Buy and Sell Stock II
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
if(prices.size()<=)
return ;
else{
int K=k,maxProf=;
if (k >= prices.size() / ) return quickSolve(prices);
vector<vector<int>> dp(K+,vector<int>(prices.size(),));
for(int i=;i<=K;i++)
{
int tmpMax=-prices[];
for(int j=;j<prices.size();j++)
{
tmpMax=max(tmpMax,dp[i-][j-]-prices[j-]);
dp[i][j]=max(dp[i][j-],prices[j]+tmpMax);
maxProf=max(maxProf,dp[i][j]);
}
}
return maxProf;
}
}
int quickSolve(vector<int>& prices)
{
int ans=;
for(int i=;i<prices.size()-;i++)
{
if(prices[i]<prices[i+])ans+=prices[i+]-prices[i];
}
return ans;
}
};
5. Best Time to Buy and Sell Stock with Cooldown
题意:给定一个数组prices,prices[i]代表第i天股票的价格。让你进行若干次买卖,求最大利润
- 你每次只能买一支而且在再次买入之前必须出售之前手头上的股票(就是手头上最多有一支股票)
- 每次出售需要休息一天才能再次买入
思路:对于某一天的最大收益,分两种情况,一种是这天存了一支股票,另一种是手里没有股票,双状态DP
sell[i] 卖出操作的最大利润。它需要考虑的是,第i天是否卖出。(手上有stock在第i天所能获得的最大利润)
buy[i] 买进操作的最大利润。它需要考虑的是,第i天是否买进。(手上没有stock在第i天所能获得的最大利润)
所以,有状态转移方程
- buy[i] = max(buy[i-1] , sell[i-2] – prices[i]) // 休息一天再买入,所以是sell[i-2]在状态转移
- sell[i] = max(sell[i-1], buy[i-1] + prices[i])
最后显然有sell[n-1] > buy[n-1] 所以我们返回sell[n-1]
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.size() < ) return ;
vector<int> buy(prices.size(), ), sell(prices.size(), );
buy[] = -prices[];
buy[] = max(-prices[], -prices[]); //注意开始手里没有stock
sell[] = max(, buy[] + prices[]);
for (int i = ; i < prices.size(); i++) {
sell[i] = max(sell[i - ], buy[i - ] + prices[i]);
buy[i] = max(buy[i - ], sell[i - ] - prices[i]);
}
return sell[prices.size() - ];
}
};
精简版:
prev_sell用来存储sell[i-2],由于buy的值要么取buy[i-1],要么为prev_sell-price[i],当为prev_sell-price[i]时,sell一定取前一次的sell,所以不影响sell的新值,因此prev_buy不必要。
class Solution {
public:
int maxProfit(vector<int> &prices) {
int buy(INT_MIN), sell(), prev_sell(), prev_buy;
for (int price : prices) {
prev_buy = buy; // not necessary
buy = max(prev_sell - price, buy);
prev_sell = sell;
sell = max(prev_buy + price, sell);
}
return sell;
}
};
6. Best Time to Buy and Sell Stock with Transaction Fee
题目大意:给定股票的价格,以及每次交易需要的花费fee,求能获得的最大利润
思路:双状态DP,类似于Best Time to Buy and Sell Stock with Cooldown
状态的定义:对于第i天的最大收益,应分成两种情况,一是该天结束后手里没有stock,可能是保持前一天的状态也可能是今天卖出了,此时令收益为sold;二是该天结束后手中有一个stock,可能是保持前一天的状态,也可能是今天买入了,用hold表示。由于第i天的情况只和i-1天有关,所以用两个变量sold和hold就可以,不需要用数组。
sold 考虑到第i天为止卖出后的收益,hold考虑到第i天为止买入持有收益
则有:
- sold[i] = max(sold[i-1], hold[i-1] + prices[i] – fee)
- hold[i] = max(hold[i-1], sold[i-1] – prices[i])
需要注意sold和hold的初始值,最终输出sold,因为最后一天的情况一定是手里没有stock的
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
vector<int> sold(prices.size(),), hold=sold;
hold[]=-prices[];
sold[]=;
for(int i=;i<prices.size();i++)
{
sold[i]=max(sold[i-],hold[i-]+prices[i]-fee);
hold[i]=max(hold[i-],sold[i-]-prices[i]);
}
return sold.back();
}
};
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int cash=;//the maxPro you have if you don't have a stock that day
int hold=-prices[];//the maxPro you have if you have a stock that day, if you have a stock the first day,hold=-prices[0]
int i;
for(i=;i<prices.size();i++){
cash=max(cash,hold+prices[i]-fee);//cash in day i is the maxvalue of cash in day i-1 or you sell your stock
hold=max(hold,cash-prices[i]); // 如果买卖不同时进行,不记录过去也可以,如果买卖同时进行,没有fee的II题相当于没有交易,这题有fee则同一天买卖会亏。因此存prev_cash和直接用today’s cash等价
}
return cash;
}
本题可以贪心求:
贪心选择的关键是找到一个最大后是不是能够卖掉stock,重新开始寻找买入机会。比如序列1 3 2 8,如果发现2小于3就完成交易买1卖3,此时由于fee=2,(3-1-fee)+(8-2-fee)<(8-1-fee),所以说明卖早了,令max是当前最大price,当(max-price[i]>=fee)时可以在max处卖出,且不会存在卖早的情况,再从i开始重新寻找买入机会
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int profit=;
int curProfit=;
int minP=prices[];
int maxP=prices[];
int i;
for(i=;i<prices.size();i++){
minP=min(minP,prices[i]);
maxP=max(maxP,prices[i]);
curProfit=max(curProfit,prices[i]-minP-fee);
if((maxP-prices[i])>=fee){//can just sell the stock at maxP day.
profit+=curProfit;
curProfit=;
minP=prices[i];
maxP=prices[i];
}
}
return profit+curProfit;//the last trade have to be made if there is some profit
}
curProfit记录了当前一次交易能得到的最大收益,只有当maxP-prices[i]>=fee时,才将curProfit累加到总的收益中。最后一次交易不需要考虑是否早卖了,所以直接累加最后一次的curProfit
[LeetCode] Best Time to Buy and Sell Stock 6道合集【DP】的更多相关文章
- LeetCode:Best Time to Buy and Sell Stock I II III
LeetCode:Best Time to Buy and Sell Stock Say you have an array for which the ith element is the pric ...
- [LeetCode] Best Time to Buy and Sell Stock with Cooldown 买股票的最佳时间含冷冻期
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- [LeetCode] Best Time to Buy and Sell Stock IV 买卖股票的最佳时间之四
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- [LeetCode] Best Time to Buy and Sell Stock III 买股票的最佳时间之三
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- [LeetCode] Best Time to Buy and Sell Stock II 买股票的最佳时间之二
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- [LeetCode] Best Time to Buy and Sell Stock 买卖股票的最佳时间
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...
- LEETCODE —— Best Time to Buy and Sell Stock II [贪心算法]
Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a ...
- LeetCode Best Time to Buy and Sell Stock IV
原题链接在这里:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/ 题目: Say you have an array ...
- [LeetCode] Best Time to Buy and Sell Stock with Transaction Fee 买股票的最佳时间含交易费
Your are given an array of integers prices, for which the i-th element is the price of a given stock ...
随机推荐
- SQL Server Profiler 常见问题总结
1.跟踪指定数据库 SELECT DB_ID('数据名称') 原文:https://jingyan.baidu.com/article/647f0115be128a7f2048a87d.html 2. ...
- 【转】Java并发编程:并发容器之ConcurrentHashMap
JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法的代价就是严重降低了 ...
- BZOJ2038 [2009国家集训队]小Z的袜子 莫队+分块
作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从 ...
- xclip for windows
下载源码和可执行文件 xclip.7z // The MIT License (MIT) // Copyright (c) 2014 Rapptz // Permission is hereby gr ...
- Ubuntu升级GCC到gcc4.8
http://www.qtcn.org/bbs/apps.php?q=diary&a=detail&did=1456&uid=139371Ubuntu最新gcc版本在ppa:u ...
- PID控制器开发笔记之九:基于前馈补偿的PID控制器的实现
对于一般的时滞系统来说,设定值的变动会产生较大的滞后才能反映在被控变量上,从而产生合理的调节.而前馈控制系统是根据扰动或给定值的变化按补偿原理来工作的控制系统,其特点是当扰动产生后,被控变量还未变化以 ...
- functions 示例
示例1: ","字符串截取 CREATE OR REPLACE FUNCTION splitstr(p_string IN VARCHAR2, p_delimiter IN VA ...
- Oracle11g 体系结构
一:Oracle11g 体系结构 二:逻辑储存结构 二.1:数据块(data blocks) ----通过 v$parameter数据字典来查询oracle标准数据块的大小. SYS@orcl> ...
- js中return false,return,return true的用法及差别
起首return作为返回关键字,他有以下两种返回体式格式 1.返回把握与函数成果 语法为:return 表达式; 语句停止函数履行,返回调用函数,并且把表达式的值作为函数的成果 2.返回把握无函数成果 ...
- 【深度学习】吴恩达网易公开课练习(class1 week3)
知识点梳理 python工具使用: sklearn: 数据挖掘,数据分析工具,内置logistic回归 matplotlib: 做图工具,可绘制等高线等 绘制散点图: plt.scatter(X[0, ...