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).
Show Tags
Have you met this question in a real interview?
思路1: brut force,分解成两段,然后分别求profit,然后求全局的sum最大;O(N^2)
class Solution {
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0){
return 0;
}
int a = 0; int b = 0;
int c = 0;
for(int i=0; i<prices.length; i++){
a = profit(prices, 0, i);
b = profit(prices, i, prices.length);
c = Math.max(c, a+b);
}
return c;
}
public int profit(int[] prices, int start, int end) {
int profit = 0;
int min = prices[start];
if(start< end) {
for(int i=start+1; i<end; i++){
min = Math.min(min, prices[i]);
if(prices[i]>prices[i-1]){
profit = Math.max(profit, prices[i]-min);
}
}
}
return profit;
}
}
改进:
改进的方法就是动态规划了,那就是第一步扫描,先计算出子序列[0,…,i]中的最大利润,用一个数组保存下来,那么时间是O(n)。
第二步是逆向扫描,计算子序列[i,…,n-1]上的最大利润,这一步同时就能结合上一步的结果计算最终的最大利润了,这一步也是O(n)。
所以最后算法的复杂度就是O(n)的。
思想:从左往右数,要记录最小值,max(profit[i-1], prices[i]-min)
从右往左数,要记录最大值,减去当前的,才是最大profit,记录最小值没有用,因为方向不一样,只能从左往右买卖。 max(maxvalue - prices[i], profit[i+1])
public class Solution {
public int maxProfit(int[] prices) {
if(prices.length == 0) return 0;
int[] leftprofit = new int[prices.length];
int[] rightprofit = new int[prices.length];
int min = prices[0];
leftprofit[0] = 0;
for(int i=1; i<prices.length; i++){
min = Math.min(prices[i],min);
leftprofit[i] = Math.max(leftprofit[i-1],prices[i]-min);
}
int max = prices[prices.length-1];
rightprofit[prices.length-1] = 0;
for(int i=prices.length-2; i>=0; i--){
max = Math.max(prices[i+1],max);
rightprofit[i] = Math.max(rightprofit[i+1],max-prices[i]);
}
int finalmax = Integer.MIN_VALUE;
for(int i=0; i<prices.length; i++){
finalmax = Math.max(finalmax,leftprofit[i]+rightprofit[i]);
}
return finalmax;
}
}