题目描述
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.
e.g.
3 4 2 1 6 9 2 3 8
Best choice
buy at 4th day and sell at 6th day
and buy at 7th day and sell at 9th day
算法分析
这道题如果直接做会比较难想到直接的状态转移函数,但是如果我们把这个大问题转化为两个小的问题的话,就容易解决很多。我们可以把这个问题想成,选择一种方法在第 i 天前最多赚的钱 与 第 i 天后最多赚的钱之和最大。对于这两个子问题实际上容易解决很多。
对于第一个子问题:
我们设一个数组 pre,来保存在第 i 天前赚取最多的利润
我们再设置一个int类型min_buy来保存在第i 天前买入的最低价,然后用状态转移方程就可以算出第 i 天前的最大利润了
pre[1] = 0
pre[i] = max(pre[i-1], prices[i] - min_buy)
i = 2, 3,4, ……, n
对于第二个自问题:
我们可以类似的设一个数组 post, 来保存在第 i 天 后赚取最多的利润
然后类似设置一个int类型max_sell 来保存在第i天后卖出的最高价,然后用状态转移方程可以算出第 i 天 后的最大利润
post[n] = 0
post[i] = max(post[i+1], max_sell - prices[i])
i = 1,2 ,3 ,4, …… ,n-1
按照pre数组和post数组,我们只需要用O(N)的时间遍历一遍挑出
max{ pre[i] + post[i]} i = 1 ,2 ,3, …… n
这三部分的时间复杂度都是O(N), 所以这个算法总的时间复杂度就是O(N), 空间复杂度为O(N)
代码如下
int maxProfit(vector<int>& prices) {
vector<int> pre(prices.size()),post(prices.size());
int max_earn=0;
int min_buy = prices[0];
for(int i = 0 ; i < prices.size();i++){
min_buy = min(prices[i],min_buy);
max_earn= max(max_earn,prices[i]-min_buy);
pre[i] = max_earn;
}
max_earn = 0;
int max_sell = prices[prices.size()-1];
for(int i = prices.size()-1; i>=0 ; i--){
max_sell = max(prices[i],max_sell);
max_earn = max(max_earn,max_sell-prices[i]);
post[i] = max_earn;
}
int ans = 0;
for(int i = 0 ; i < prices.size(); i++){
ans = max(ans,pre[i]+post[i]);
}
return ans;
}