Leetocode全部5道买卖股票问题总结(121+122+123+188+309)

题目1----121. 买卖股票的最佳时机I:

链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

解答:

限制只能买入卖出一次

DP1:

buy[i]记录截止到第i天是买入的状态的最小花费(值为负数)

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int>& prices) {
 4         if(prices.size()<2){
 5             return 0;
 6         }
 7         int n=prices.size(),res=0;
 8         vector<int> buy(n,0);
 9         buy[0]=-prices[0];
10         for(int i=1;i<n;++i){
11             res=max(buy[i-1]+prices[i],res);
12             buy[i]=max(-prices[i],buy[i-1]);
13         }
14         return res;
15     }
16 };

严格来说这个不算dp,计算第i天的情况时,只用到了buy[i-1]的数据。。所以前面保存的数据是没有意义的。

DP2:

dp[i]记录第i天当天卖出的最大利润,则最大利润一定等于之前某天买今天卖。

i):首先可以昨天买今天卖。

ii):还可以之前某天买今天卖。dp[i-1]等于昨天之前买入,i-1天卖出的最大利润,那么i-1天不卖,改为第i天卖也可以得到一个利润。

两个利润取最大。

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int>& prices) {
 4         if(prices.size()<2){
 5             return 0;
 6         }
 7         int n=prices.size();
 8         vector<int> dp(n,0);
 9         dp[0]=0;
10         int res=0;
11         for(int i=1;i<n;++i){
12             dp[i]=max(0,prices[i]-prices[i-1]);
13             dp[i]=max(dp[i],dp[i-1]-prices[i-1]+prices[i]);
14             res=max(res,dp[i]);
15         }
16         return res;
17     }
18 };

遍历:

和DP一样都是O(N)时间,和第一种dp一样想法,只是不用记录dp数组了。毕竟考察i的时候,只需要buy[i-1]的数据。
思路:最高利润出现在:买入为价格最低时,卖出为买入之后价格最高时。
故当更新最小值价格时,之前的最大价格要舍弃,从当前索引继续考察。

 1 class Solution:
 2     def maxProfit(self, prices: List[int]) -> int:
 3         l=len(prices)
 4         if l<2:
 5             return 0
 6         _min,_max=0,0
 7         i=0
 8         res=0
 9         while i<l:
10             if prices[i]<prices[_min]:
11                 _min=i
12                 _max=i
13             if prices[i]>prices[_max]:
14                 _max=i
15             res=max(res,prices[_max]-prices[_min])
16             i+=1
17         return res

题目2----122. 买卖股票的最佳时机II:

链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

解答:

无限制次数的买入卖出

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int>& prices) {
 4         int n=prices.size();
 5         if(n<2){return 0;}
 6         vector<int> buy(n,0),sell(n,0);
 7         buy[0]=-prices[0];
 8         for(int i=1;i<n;++i){
 9             sell[i]=max(sell[i-1],prices[i]+buy[i-1]);//之前卖今天不卖 or 之前买今天卖
10             buy[i]=max(buy[i-1],sell[i-1]-prices[i]);//之前买今天不买 or 之前卖了今天买
11         }
12         return sell[n-1];
13     }
14 };

题目3----123. 买卖股票的最佳时机III:

链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

解答:

限制最多两次买入卖出

定义了4个dp数组,分别是

buy1[i]:第i天是第一次买入的状态

sell[i]:第i天是第一次卖出的状态

buy2、sell2同理。

由于一开始还不能第二次买和第二次卖,所以赋值为负无穷。

 1 class Solution {
 2 public:
 3     #define inf INT_MIN
 4     int maxProfit(vector<int>& prices) {
 5        int n=prices.size();
 6        if(n<2){return 0;}
 7        vector<int> buy1(n,0),sell1(n,0),buy2(n,inf),sell2(n,inf);
 8        buy1[0]=-prices[0];
 9        for(int i=1;i<n;++i){
11            sell1[i]=max(prices[i]+buy1[i-1],sell1[i-1]);
12            buy1[i]=max(-prices[i],buy1[i-1]);
13            sell2[i]=max(buy2[i-1]+prices[i],sell2[i-1]);
14            buy2[i]=max(buy2[i-1],sell1[i-1]-prices[i]);
16        }
17        return max(0,max(sell2[n-1],sell1[n-1]));
18     }
19 };

方法2:先计算1次买卖最大的利润sell1[i]。再计算从第i天开始再买卖一次最大的利润sell2[i]。

第一次买卖是从前向后求(因为左侧是固定的),第二次买卖是从后向前求(因为右侧是固定的)

 1 class Solution {
 2 public:
 3     #define inf INT_MIN
 4     int maxProfit(vector<int>& prices) {
 5        int n=prices.size();
 6        if(n<2){return 0;}
 7        vector<int> sell1(n,0),sell2(n,0);
 8        int min_buy=-prices[0];
 9        for(int i=1;i<n;++i){
10            sell1[i]=max(sell1[i-1],prices[i]+min_buy);
11            min_buy=max(min_buy,-prices[i]);
12        }
13        int res=max(0,sell1[n-1]);
14        int max_sell=prices[n-1];
15        for(int i=n-2;i>=0;--i){
16            sell2[i]=max(sell2[i+1],max_sell-prices[i]);
17            max_sell=max(max_sell,prices[i]);
18            res=max(res,sell1[i]+sell2[i]);
19        }
20        return res;
21     }
22 };

之前写过的python版本,以供参考:

 1 class Solution:
 2     def maxProfit(self, prices) -> int:
 3         l=len(prices)
 4         if l<2:
 5             return 0
 6         res=0
 7         #先算一个dp1数组
 8         #dp1[i]表示截止到第i-1天只进行一次买卖的最大利润
 9         dp1=[0 for i in range(l)]
10         max_price,min_price=prices[0],prices[0]
11         for i in range(1,l):
12             dp1[i]=max(dp1[i-1],prices[i]-min_price)
13             #对于第i天来说,1.如果当天卖:最大利润即当前卖出价格
14             #减去之前的最小买入价格,2如果不卖:最大利润和前一天的
15             #最大利润相同
16             min_price=min(min_price,prices[i])  #更新当前最小买入价格
17             max_price=max(max_price,prices[i])  #更新当前最大卖出价格
18         #对于任意k,dp1[k]表示k卖出的最大利润,
19         #那么需要求剩下k+1到n-1的最大利润
20         #倒着求,因为右边界不变始终为l-1,左边界在变化
21         #dp2[i]表示从i开始到最后只进行一次买卖的最大利润
22         res=dp1[-1]
23         # print(res)
24         dp2=[0 for i in range(l)]
25         max_price=prices[-1]
26         for i in range(l-2,-1,-1):
27             dp2[i]=max(dp2[i+1],max_price-prices[i])
28             #对于第i天,1.若当天买,则最大利润即之后的最大卖出价格减去
29             #当前买入价格,2.若当天不买,最大利润和后一天的最大利润相同
30             max_price=max(max_price,prices[i])  #更新当前最大卖出价格
31             res=max(res,dp1[i-1]+dp2[i]) if i>=1 else max(res,dp2[i])
32         # print(dp1)
33         # print(dp2)
34         return res

后来发现其实不需要存储dp数组,只需要一个变量记录上一次的状态就行,但我懒,就不写了,反正内存大任性

题目4----188. 买卖股票的最佳时机IV:

链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/

给定一个数组,它的第 i 个元素是一支给定的股票在第 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

这道题限制买卖次数最大为k,是一个变量。

设二维dp数组。dp[i][j]表示截止到i最多完成j笔交易的最大利润。

截止第i天,最大利润首先可以是之前的最大利润,即之前就完成了j笔交易,第i天不卖。

当然第i天也可以卖,那么本拨交易的买入最晚也得是i-1天,那么i-2天之前(包含i-2天)就必须要完成j-1笔交易。

用一个max值表示截止到前一天完成j-1笔交易、并且是待卖出状态的最大利润。

递推方程为:dp[i][j]=max(dp[i-1][j],max+prices[i])

另外每次循环中要更新max的值。

另外有用例k给的无限大,那么申请dp数组时会爆栈。需要判断一下k和价格数量的关系,如果k太大,转化为上面第2题的无限次的买卖股票问题。

前面的问题1和问题3只是这道题的特殊情况,代码直接复制过去就可以运行。

 1 class Solution {
 2 public:
 3     int maxProfit(int k, vector<int>& prices) {
 4         if(prices.empty()){
 5             return 0;
 6         }
 7         int n=prices.size();
 8         if(2*k<n){
 9             vector<vector<int>> dp(n,vector<int>(k+1,0));
10             //dp[i][j]表示截止第i天完成最多j次交易得到的最大收益
11             for(int j=1;j<k+1;++j){
12                 int _max=-prices[0];
13                 for(int i=1;i<n;++i){
14                     dp[i][j]=max(dp[i-1][j],_max+prices[i]);
15                     _max=max(dp[i-1][j-1]-prices[i],_max);
16                 }
17             }
18             return dp.back().back();
19         }
20         else{//k太大,相当于可以无限次交易
21             vector<int> dp(n,0);
22             //dp[i]表示截止第i+1天得到的最大收益
23             int _max=-prices[0];
24             for(int i=1;i<n;++i){
25                 dp[i]=max(dp[i-1],_max+prices[i]);
26                 _max=max(_max,dp[i]-prices[i]);
27             }
28             return dp.back();
29         }
30         return 0;
31     }
32 };

题目5----309. 最佳买卖股票时机含冷冻期:

链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。?

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

这道题多了一个冷冻期的限制:卖出之后要至少休息一天才能买入

那么理所当然的,多设立一个dp数组以表示冷冻期的状态:

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int>& prices) {
 4         if(prices.size()<2){
 5             return 0;
 6         }
 7         int n=prices.size();
 8         vector<int> buy(n,0),sell(n,0),freeze(n,0);
 9         //buy[i]、sell[i]、freeze[i]分别表示第i天
10         //买入、卖出、不买不卖的最大收益(包含买股票花的钱)
11         buy[0]=-prices[0];
12         int res=0;
13         for(int i=1;i<n;++i){
14             buy[i]=max(buy[i-1],freeze[i-1]-prices[i]);
15             sell[i]=max(sell[i-1],buy[i-1]+prices[i]);
16             freeze[i]=max(sell[i-1],freeze[i-1]);
17             res=max(sell[i],res);
18         }
19         return res;
20     }
21 };

也可以仿照第四题的解法,用一个max值保存截止前一天待卖出状态的最大利润,不过更新max的时候,要注意冷冻期的要求。所以_max=max(_max,dp[i-2]-prices[i]),即截止i-2天卖出的最大利润,休息一天,第i天买入。之前的题目是_max=max(_max,dp[i-1]-prices[i]),注意二者的区别,虽然只是1和2的数字不同,但却是整道题的关键

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int>& prices) {
 4         int n=prices.size();
 5         if(n<2){return 0;}
 6         vector<int> sell(n,0);
 7         sell[1]=max(0,prices[1]-prices[0]);
 8         int _max=max(-prices[0],-prices[1]);
 9         for(int i=2;i<n;++i){
10             sell[i]=max(sell[i-1],_max+prices[i]);
11             _max=max(_max,sell[i-2]-prices[i]);
12         }
13         // for(int x:sell){cout<<x<<" ";};
14         return sell[n-1];
15     }
16 };

完结撒花????

明天就要华为机试了,坏运气给??爬

2020-02-19 02:01:09

原文地址:https://www.cnblogs.com/FdWzy/p/12288157.html

时间: 2024-09-29 18:48:41

Leetocode全部5道买卖股票问题总结(121+122+123+188+309)的相关文章

121. 122. 123. 188. Best Time to Buy and Sell Stock *HARD* -- 买卖股票

121. Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

[LeetCode] 123. Best Time to Buy and Sell Stock III 买卖股票的最佳时间 III

Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Note:You may not engage in multiple transactions at the same time (ie,

leetcode——Best Time to Buy and Sell Stock III 买卖股票最大收益(AC)

Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Note: You may not engage in multiple transactions at the same time (ie,

2:买卖股票的最佳时机

描述:假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. 样例 给出一个数组样例 [3,2,3,1,2], 返回 1 class Solution { public: /** * @param prices: Given an integer array * @return: Maximum profit */ int maxProfit(vector<int> &prices) { // wr

【LeetCode-面试算法经典-Java实现】【121-Best Time to Buy and Sell Stock(最佳买卖股票的时间)】

[121-Best Time to Buy and Sell Stock(最佳买卖股票的时间)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (ie, buy one

买卖股票的最佳时机I II III IV

I 假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. II 假设有一个数组,它的第i个元素是一个给定的股票在第i天的价格.设计一个算法来找到最大的利润.你可以完成尽可能多的交易(多次买卖股票).然而,你不能同时参与多个交易(你必须在再次购买前出售股票). III 假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格.设计一个算法来找到最大的利润.你最多可以完成两笔交易. 样例 给出一个样例数组

删除排序数组中的重复数字、买卖股票的最佳时机、爬楼梯

题目1:删除排序数组中的重复数字 描述:给定一个排序数组,在原数组中删除重复出现的数字,使得每个元素只出现一次,并且返回新的数组的长度. 不要使用额外的数组空间,必须在原地没有额外空间的条件下完成. 题目2:买卖股票的最佳时机 描述:假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. 题目3:爬楼梯 描述:假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶

代码题(6)— 买卖股票的最佳时机

1.121. 买卖股票的最佳时机(仅限一次) 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出股票. 示例 1: 输入: [7,1,5,3,6,4] 输出: 5 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 . 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格. c

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

买卖股票的最佳时机III 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票). 示例 1: 输入: [3,3,5,0,0,3,1,4] 输出: 6 解释: 在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 . 随后,在第 7 天(股票价格 = 1)的时候买入,在