题目:
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, you must sell the stock before you buy again).
延续前面两道题目,本题是只可以进行两次交易,首先想到的是先求出第一次交易的最大利润,然后再进行第二次交易,两次交易之间不能重叠。所以我们使用一个数组保存第一次遍历时每一步的最大利润,然后再进行反向遍历,找出第二次交易的利润。代码入下:
public int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2)
return 0;
int [] maxBefore = new int[len];
int min = prices[0];
for(int i=1; i<len; i++){
maxBefore[i] = Math.max(maxBefore[i-1], prices[i] - min);
min = Math.min(min, prices[i]);
}
int max = prices[len - 1];
int ret = 0;
for(int i=len-2; i>=0; i--){
//找到后面最大的价格
max = Math.max(prices[i], max);
//利润 = 最大价格 - 当前价格 + 此时交易时第一次的利润
//取最大值
ret = Math.max(ret, max - prices[i] + maxBefore[i]);
}
return ret;
}
这种方法因为使用了两次循环,所以耗时较长,击败了18%的用户,而且使用了额外的O(n)存储空间。接下来我们需要改进算法,在看完discuss之后有了改进思路,基本想法是使用四个变量来表示第一次买入,第一次卖出,第二次买入,第二次卖出。然后再遍历的同时对其进行更新。代码入下:
public int maxProfit(int[] prices) {
int len = prices.length;
if(len <= 1) return 0;
int a, b, c, d;
//d表示从后向前遍历的最大值,c表示第一次交易之后的最大利润,b表示第二次交易之前的最大值,a表示第二次交易之后的利润之和。
d = Math.max(prices[len-1], prices[len-2]);
c = Math.max(prices[len-1] - prices[len-2], 0);
b = d;
a = c;
for(int i=len-3; i>=0; i--) {
//这里结合上面每个变量的意义进行理解,为什么每个变量更新的公式如下。
a = Math.max(b - prices[i], a);
b = Math.max(prices[i] + c, b);
c = Math.max(d - prices[i], c);
d = Math.max(prices[i], d);
}
return a;
}
这种方法可以击败58%的用户,还有另外一种解法,思路同上,如下所示,可以击败76%的用户:
public int maxProfit(int[] prices) {
// these four variables represent your profit after executing corresponding transaction
// in the beginning, your profit is 0.
// when you buy a stock ,the profit will be deducted of the price of stock.
int firstBuy = Integer.MIN_VALUE, firstSell = 0;
int secondBuy = Integer.MIN_VALUE, secondSell = 0;
for (int curPrice : prices) {
if (firstBuy < -curPrice) firstBuy = -curPrice; // the max profit after you buy first stock
if (firstSell < firstBuy + curPrice) firstSell = firstBuy + curPrice; // the max profit after you sell it
if (secondBuy < firstSell - curPrice) secondBuy = firstSell - curPrice; // the max profit after you buy the second stock
if (secondSell < secondBuy + curPrice) secondSell = secondBuy + curPrice; // the max profit after you sell the second stock
}
return secondSell; // secondSell will be the max profit after passing the prices
}