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).
思路一,既然是两次交易,那么我就求所有可能的两次交易,即profit=max{(0,i),(i,n)},0<=i<n,最终时间复杂度为O(n2)
<span style="font-size:18px;">public class Solution {
public int maxProfit(int[] prices) {
if(prices.length == 0){
return 0;
}
int profit = 0;
for(int i = 0; i < prices.length-1 ; i ++){
profit = pro(0,i,prices) + pro(i+1,prices.length-1,prices) > profit ? pro(0,i,prices) + pro(i+1,prices.length-1,prices) : profit;
}
return profit;
}
public int pro(int i, int j,int[] prices){//i到j这几天的最大收益
if(i == j){
return 0;
}
int buy = prices[i];
int sell = prices[j];
int profit = sell - buy;
int index = i + 1;
while(index <= j){
if(prices[index] > sell){
sell = prices[index];
profit = sell - buy > profit? sell - buy: profit;
}else if(prices[index] < buy){
sell = prices[index];
buy = prices[index];
}
index ++;
}
return profit;
}
}</span>
思路二:
感觉是DP,但是怎么也想不到,试了试解法一,结果不出所料,Time Limit Exceeded
考虑解法一的缺点,当求第i天的收益时,直接就是按不就班的从第0天计算到第i天,那么计算所得的第i-1天的收益直接丢弃不使用,那么思考一下,是否可以利用辛辛苦苦得到的第i-1天收益的数据?答案是可以,如果我们记录了第i-1天之前的最小值min,那么第i天的收益该怎么计算,一定是DP[i]=max(DP[i-1],prices[i]-min)。
http://blog.unieagle.net/2012/12/05/leetcode%E9%A2%98%E7%9B%AE%EF%BC%9Abest-time-to-buy-and-sell-stock-iii%EF%BC%8C%E4%B8%80%E7%BB%B4%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/
public class Solution {
public int maxProfit(int[] prices) {
if(prices.length <= 1){
return 0;
}
int[] left = new int[prices.length];//存储从左向右扫描得到的第i天最大的收益
left[0] = 0;
int min = prices[0];//第i天之前最小的值
//需找DP方程
//当prices[i] - min > left[i-1] 时 left[i] = prices[i] - min;
//当prices[i] - min < left[i-1] 时 left[i] = left[i-1],且min = MIN(prices[i],min)
for(int i = 1; i < prices.length ; i ++){
left[i] = prices[i] - min > left[i-1] ? prices[i] - min : left[i-1];
min = prices[i] < min ? prices[i]: min;
}
//同理
int[] right = new int[prices.length];//存储从右向左扫描得到的第i天的最大收益
right[prices.length-1] = 0;
int max = prices[prices.length - 1];
for(int i = prices.length - 2 ; i >= 0 ; i--){
right[i] = max - prices[i] > right[i+1] ? max - prices[i] : right[i+1];
max = prices[i] > max ? prices[i] : max;
}
int profit = left[0] + right[0];
for(int i = 1 ; i < prices.length ; i ++){
if(left[i] + right[i] > profit){
profit = left[i] + right[i];
}
}
return profit;
}
}