[LeetCode] Best Time to Buy and Sell Stock III

 将Best Time to Buy and Sell Stock的如下思路用到此题目

思路1:第i天买入,能赚到的最大利润是多少呢?就是i + 1 ~ n天中最大的股价减去第i天的。

思路2:第i天买出,能赚到的最大利润是多少呢?就是第i天的价格减去 0~ i-1天中最小的。

和前两道题比起来的话,这道题最难了,因为限制了交易次数。
解决问题的途径我想出来的是:既然最多只能完成两笔交易,而且交易之间没有重叠,那么就divide and conquer。
设i从0到n-1,那么针对每一个i,看看在prices的子序列[0,...,i][i,...,n-1]上分别取得的最大利润(第一题)即可。
这样初步一算,时间复杂度是O(n2)。


改进:
改进的方法就是动态规划了,那就是第一步扫描,先计算出子序列[0,...,i]中的最大利润,用一个数组保存下来,那么时间是O(n)。
第二步是逆向扫描,计算子序列[i,...,n-1]上的最大利润,这一步同时就能结合上一步的结果计算最终的最大利润了,这一步也是O(n)。
所以最后算法的复杂度就是O(n)的。

/*
解释:
首先,因为能买2次(第一次的卖可以和第二次的买在同一时间),但第二次的买不能在第一次的卖左边。
所以维护2个表,f1和f2,size都和prices一样大。
意义:
f1[i]表示 -- 截止到i下标为止,左边所做交易能够达到最大profit;[0,...,i]的利润
f2[i]表示 -- 截止到i下标为止,右边所做交易能够达到最大profit;[i,...,n-1]的利润
那么,对于f1 + f2,寻求最大即可。
*/

 对于f1[i],求解过程中用price[i] 减去之前的最小值 和 f1[i-1]做比较,取最大值

动态规划转移方程 f1[i] = max(f1[i-1], price[i]- min)

对于f2[i],求解过程中用后面的最大值减去price[i]和f2[i+1]做比较,取最大值

 动态规划转移方程 f2[i] = max(f2[i+1], max-price[i])

思路解释完毕,上code:

minX[i] 表示0 到 i 的最小值 的price

max[i] 表示i到n-1的最大值的price

 1 class Solution {
 2     public:
 3         int maxProfit(vector<int> &prices) {
 4             if (prices.size() == 0)
 5                 return 0;
 6 
 7             vector<int> f1(prices.size());
 8             vector<int> f2(prices.size());
 9 
10             vector<int> minX(prices.size());
11             vector<int> maxX(prices.size());
12 
13             minX[0] = prices[0];
14             for(int i = 1; i< prices.size();i++ )
15             {
16                 minX[i] = min(minX[i-1], prices[i]);
17             }
18 
19             maxX[prices.size()-1] = prices[prices.size()-1];
20             for(int i = prices.size() -2; i >=0; i-- )
21             {
22                 maxX[i] = max(maxX[i+1], prices[i]);
23             }
24 
25             f1[0] = 0;
26             for(int i = 1; i< prices.size();i++ )
27             {
28                 f1[i] = max(f1[i-1],prices[i]-minX[i]);
29             }
30 
31             f2[prices.size()-1] = 0;
32             for(int i = prices.size() -2; i >=0; i-- )
33             {
34                 f2[i] = max(f2[i+1],maxX[i]- prices[i]);
35             }
36 
37 
38             int sum = 0;
39 
40             for(int i = 1; i< prices.size();i++ )
41                 sum = max(sum, f1[i] + f2[i]);
42 
43             return sum;
44 
45         }
46 };

优化:可以对上述code稍微优化一下,maxX 和minX array 并不需要,只要保留一个变量mini和maxX即可,不过由于f1和f2 的存在,空间复杂度还是O(n)

 1 class Solution {
 2     public:
 3         int maxProfit(vector<int> &prices) {
 4             if (prices.size() == 0)
 5                 return 0;
 6 
 7             vector<int> f1(prices.size());
 8             vector<int> f2(prices.size());
 9     
10             int mini = prices[0];
11             f1[0] = 0;
12             for(int i = 1; i< prices.size();i++ )
13             {   
14                 f1[i] = max(f1[i-1],prices[i]-mini);
15                 mini = min(mini, prices[i]);
16             }   
17 
18             int maxi = prices[prices.size()-1];
19             f2[prices.size()-1] = 0;
20             for(int i = prices.size() -2; i >=0; i-- )
21             {   
22                 f2[i] = max(f2[i+1],maxi - prices[i]);
23                 maxi = max(maxi, prices[i]);
24             }   
25 
26             int sum = 0;
27 
28             for(int i = 1; i< prices.size();i++ )
29                 sum = max(sum, f1[i] + f2[i]);
30 
31             return sum;
32 
33         }   
34 };
原文地址:https://www.cnblogs.com/diegodu/p/3822539.html