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. vsftp、ftps 搭建

    今天公司某个产品预上线,该产品需要向政府某部门提供一些数据. 该部门提交数据需要使用ftps,苦逼的我只能是测试环境搭建一套,用来测试提交数据. 先自行科普下ftps. 一.搭建vsftp 安装vsf ...

  2. 对比Dijakstra和优先队列式分支限界

    Dijakstra和分支限界都是基于广度优先搜索,如果说两者都是生成一棵树,那Dijakstra总是找距离树根最近的(属于贪心算法),优先队列式分支限界是在层遍历整棵搜索树的同时剪去达不到最优的树枝. ...

  3. 微信小程序开发记录

    顶栏banner代码 /**app.wxss**/ .container { height: 100%; display: flex; flex-direction: column; align-it ...

  4. 修改主机IP地址

    IP:由192.168.1.1~192.168.1.254. 先使用电脑以动态IP的方式自动获取ip地址联网,然后通过以下方法查询子网掩码和默认网关地址:

  5. 【ORIGINATE】详解

    originate 用法如下: originate <call url> <exten> |&<application_name>(<app_args ...

  6. bootstrap的treeview使用方法

    首先引入文件: <link href="./css/bootstrap.css" rel="stylesheet"> <script src= ...

  7. 洛谷P3345 [ZJOI2015]幻想乡战略游戏 [动态点分治]

    传送门 调了两个小时,终于过了-- 凭啥人家代码80行我180行啊!!! 谁叫你大括号换行 谁叫你写缺省源 思路 显然,补给点所在的位置就是这棵树的带权重心. 考虑size已知时如何找重心:一开始设答 ...

  8. JS知识点随笔

    1.为什么 0.1 + 0.2 != 0.3? 原因: 因为 JS 采用 IEEE 754 双精度版本(64位),并且只要采用 IEEE 754 的语言都有该问题. 我们都知道计算机是通过二进制来存储 ...

  9. liunx 安装redis 4.0

    liunx 上安装redis 4.0.1 第一步:将 redis-4.0.1.tar.gz 压缩问上传至/home目录下 第二步: 解压文件  tar -zxvf  redis-4.0.1.tar.g ...

  10. Confluence 6 数据中心的 SAML 单点登录最佳实践和故障排除

    最佳实践 SAML 授权仅仅在有限的时间进行校验.你需要确定运行你的应用的计算机时间与 IdP 的时间是同步的. 如果你应用中的用户和用户组是通过用户目录进行配置的,你通常希望用户来源目录和你的 Id ...