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. layout 的应用

    在XAF的开发中,详细Detail 或组合DashBoard页面,需要使用 LayoutControl 进行控件排列,下面讲述如何通过写代码进行操作. 0.DevExpress 的布局控件(DevEx ...

  2. MySQL用户授权【转】

    MySQL 赋予用户权限命令的简单格式可概括为:grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删除 数据库中所有表数据的权利. grant selec ...

  3. 一个优秀windows C++ 程序员该有哪些知识

  4. Python在线聊天软件(Tkinter)

    1.python2.7下安装 apt-get install python-tk 主要功能是实现客户端与服务器端的双向通信,这个小东西用到的主要知识点: 1.Python Socket:2.Pytho ...

  5. oracle 会话 解锁

    背景 这是当年第一次记录博客,当初记录的原因是感觉有些问题很少碰到,碰到有网上寻找一遍,文章很少是正好对症的,折腾半天终于解决了,但是没有记录过程,结果下次碰到又要从来一次.有的问题还极其不好找,or ...

  6. vue.js如何更改默认端口号8080为指定端口

    执行npm run dev实际是在调用根目录下的package.json 打开package.json后可发现有这样一段代码 由此可知,我们应该查看build目录下的dev-server.js文件 在 ...

  7. Day8--------------yum软件包管理

    1.url三段式:协议.域名.路径 例如:http://wan.360.cn/game 2.本地yum配置: vim /etc/yum.repos.d/local.repo [local] #固定格式 ...

  8. iOS Code Sign On Copy

    上面的图中,code sign on copy 是什么意思呢? 先看专业的解释:http://stackoverflow.com/questions/30963294/creating-ios-osx ...

  9. C# 制作向导

    1.FormBase界面:有“帮助,上一步,下一步,取消”按钮,这些按钮放置在一个Panel上. namespace DataBase {     public partial class FormB ...

  10. pytorch的学习资源

    安装:https://github.com/pytorch/pytorch 文档:http://pytorch.org/tutorials/beginner/blitz/tensor_tutorial ...