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】的更多相关文章

  1. 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 ...

  2. [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 ...

  3. [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 ...

  4. [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 ...

  5. [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 ...

  6. [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 ...

  7. 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 ...

  8. 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 ...

  9. [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 ...

随机推荐

  1. python zip文件压缩和解压

    压缩 import shutil zipOutputName = "1234" # 输出1234.zip fileType = "zip" # 文件类型zip ...

  2. mac配置supervisor

    mac配置supervisor 安装 brew install supervisor 启动 一种是手动 supervisord -c /usr/local/etc/supervisord.ini 让s ...

  3. 结构数组新发现之直接初始化《leetcode-合并区间》

    leetcode有时候会要求一些奇怪(陌生)的数据形式,刷题因为数据形式卡住了真的很不好... 合并区间里定义了一个Interval的结构数组 struct Interval { int start; ...

  4. Python3学习笔记27-ConfigParser模块

    ConfigParser模块在Python3修改为configparser,这个模块定义了一个ConfigeParser类,该类的作用是让配置文件生效.配置文件的格式和window的ini文件相同,大 ...

  5. C++游戏开发需要阅读的书籍

    如果要自学游戏程序开发的话,可以看看下面的,呵呵. 游戏开发资料(PDF书都是中文版的,非英文,很多是本人自己扫描制作,从未网上发布过,所以独家啦):  1.Gamebryo 2.2游戏引擎(盛大.腾 ...

  6. CTex+WinEdt10.2安装详细教程与破解

    原文地址:https://www.cnblogs.com/xiachongkun/p/8176390.html Latex作为目前最好用的文档编排工具,以前只是简单会一点,现在也已经忘得差不多了.因为 ...

  7. jQuery中如何实现多库并存?

    多库共存就是“$ ”符号的冲突. 方法一: 利用jQuery的实用函数$.noConflict();这个函数归还$的名称控制权给另一个库,因此可以在页面上使用其他库.这时,我们可以用"jQu ...

  8. redis conf 中文详解

    # Redis示例配置文件 # 注意单位问题:当需要设置内存大小的时候,可以使用类似1k.5GB.4M这样的常见格式: # # 1k => 1000 bytes # 1kb => 1024 ...

  9. Navicat系列产品激活教程

    准备 本教程可破解12.x版本,如果教程失效请联系我 # 19.1.11 破解暂时失效,请勿更新 (如已更新请卸载重新安装老版本,数据不会丢失 http://download.navicat.com/ ...

  10. table中border-collapse的问题

    在table中,如果设置了border-collapse: collapse;,边框会合并,这时你修改top或bottom的颜色,会有问题 解决办法是:border-collapse: separat ...