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).
小米的题
题目描述
输入例子:
1,首先我们假设我们可以用O(N)的复杂度解决之买卖一次的情况,即LeetCode121点击打开链接。那么我们可以把prices分成两部分,第一部分包含第一次交易,第二部分包含第二次交易, 每一部分就是求买卖一次情况下最大收益,即LeetCode121的解法。这样我们把分成两部分的所有情况都遍历一遍就可以得到结果了。
比如 [2,1,0,1,2],我们可以这样分
[2,1,0,1,2]
[2],[1,0,1,2]
[2,1] ,[0,1,2]
[2,1,0],[1,2]
[2,1,0,1] [2]
在上面五个组合中,一定至少有一个组合包含最优解。代码如下。
static private int getProfitOnce(int[] prices, int s, int e){
int buy = prices[s];
int maxProfit = 0;
for(int i = s; i<=e; i++){
buy = Math.min(prices[i], buy);
maxProfit = maxProfit > prices[i]-buy? maxProfit: prices[i]-buy;
}
return maxProfit;
}
public static int maxProfit(int[] prices) {
int maxProfit = 0;
if(prices.length == 0) return 0;
maxProfit = getProfitOnce(prices, 0, prices.length-1);
for(int i=2; i<prices.length-1; i++){
int first = getProfitOnce(prices, 0, i-1);
int second = getProfitOnce(prices, i, prices.length-1);
int profit = first + second;
maxProfit = maxProfit > profit? maxProfit: profit;
}
return maxProfit;
}
由于分组时间复杂度为O(N),每一组找最大值的时间复杂度也为O(N)。上面的代码总时间复杂度为O(N^2)。
可惜放到LeetCode里面跑,结果超时了。那么我们只能寻找更佳的解法了。
我们依然还是分组的思想,分组就是O(N)。但是我们知道求解一个分组的复杂度任然是O(N)。 如果嵌套就是O(N^2),但是如果是并列呢,并列就是O(N)+O(N),仍然是O(N)。那么可行吗,可行。
以分组点,假如两边的分组最大利润我们已经知道了,那么我们就可以知道该点分界产生的最大利润,遍历一遍分界点,就知道那个分界点产生最大利润。
那么我们现在就要求某点初前产生的最大利润和某点初最大的利润。某点初前产生的最大利润和LeetCode121是一样的,我们直接用就行啦。
那么分界点后面的怎么求呢,那么从右向左遍历,遍历过程中存储左边的最大值,最大值和当前值之差就是当前点之后进行一次交易的最大利润了。
这样我们通过三个遍历就可以求解了,代码如下。
static public int maxProfit2(int[] prices) {
if(prices.length == 0) return 0;
int leftBuy = prices[0];
int leftMaxProfit = 0;
int[] leftProfitArray = new int[prices.length];
for(int i = 1; i< prices.length; i++){
leftBuy = Math.min(prices[i], leftBuy);
leftMaxProfit = leftMaxProfit > prices[i]-leftBuy? leftMaxProfit: prices[i]-leftBuy;
leftProfitArray[i] = leftMaxProfit;
}
int rightBuy = prices[prices.length-1];
int rightMaxProfit = 0;
int[] rightProfitArray = new int[prices.length];
for(int i = prices.length-2; i>=0 ;i --){
rightBuy = Math.max(prices[i], rightBuy);
rightMaxProfit = rightMaxProfit > rightBuy - prices[i]? rightMaxProfit:rightBuy-prices[i];
rightProfitArray[i] = rightMaxProfit;
}
int maxProfit = 0;
for(int i = 0; i < prices.length; i++){
maxProfit = Math.max(maxProfit, leftProfitArray[i] + rightProfitArray[i]);
}
return maxProfit;
}
时间和空间复杂度均为O(N)。