Say you have an array for which the ith element is the price of a given stock on day i.
I. If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
II. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
III. 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).
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package leetcode; | |
/** | |
* Sotck III Solution: DP. | |
* First, consider O(n^2) solution. Find a midmpoint i, [0,i] [i+1, n-1] find two profit of each range. --> Best Stock I solution | |
* then, i could starts from 0 to n-1, in each loop, there's two O(n). the final merge part will be O(n) | |
* O(2n^2) + O(n) -> O(n^2), now we consider optimization. | |
* | |
* DP: | |
* calculate price[0..i] --> price[0..i+1], we could use O(1) time like Stock I way but not use calculate using O(n) again. | |
* What about price[i..n-1] --> price[i+1..n-1]? Same, easy get profit[i,n-1] from profit[i+1,n-1]. | |
* left[i] stores most profit from price[0..i] | |
* right[i] stores most profit form price[i+1, n-1]. we can only calculate right[] from right to left. | |
* We use O(n) to find out the max(left[i] + right[i]) | |
* | |
* Reference: http://blog.csdn.net/fightforyourdream/article/details/14503469 | |
* | |
* Test case: | |
* prices = {1, 2, 5, 9, 4, 3, 7, 8, 5} result = 13 | |
* left = [0, 1, 4, 8, 8, 8, 8, 8, 8] | |
* right = [8, 7, 5, 5, 5, 5, 1, 0, 0] | |
* @author jeffwan | |
* @date Mar 31, 2014 | |
*/ | |
public class MaxProfit { | |
// Best Time to Buy and Sell Stock III | |
public int maxProfit3(int[] prices) { | |
if (prices == null || prices.length == 0) { | |
return 0; | |
} | |
int[] left = new int[prices.length]; // left[i] means highest profit in (0..i) | |
int[] right = new int[prices.length]; | |
// DP from left to right | |
left[0] = 0; // DP initial state | |
int min = prices[0]; | |
for (int i = 1; i < prices.length; i++) { | |
min = Math.min(min, prices[i]); | |
left[i] = Math.max(left[i - 1], prices[i] - min); | |
} | |
// DP from right to left | |
right[prices.length - 1] = 0; // DP initial state | |
int max = prices[prices.length - 1]; | |
for (int i = prices.length - 2; i >= 0; i--) { | |
max = Math.max(max, prices[i]); | |
right[i] = Math.max(right[i + 1], max - prices[i]); | |
} | |
int profit = 0; | |
for (int i = 0; i < prices.length; i++) { | |
profit = Math.max(profit, left[i] + right[i]); | |
} | |
return profit; | |
} | |
// Best Time to Buy and Sell Stock I | |
/** | |
* Solution: Find the increasing pair(lowest, highest), Only need to record lowest prices, and profit. | |
*/ | |
public int maxProfit1(int[] prices) { | |
if (prices == null || prices.length == 0) { | |
return 0; | |
} | |
int lowest = Integer.MAX_VALUE; | |
int profit = 0; | |
for (int currentPrice : prices) { | |
lowest = Math.min(lowest, currentPrice); | |
profit = Math.max(profit, currentPrice - lowest); | |
} | |
return profit; | |
} | |
// Best Time to Buy and Sell Stock II | |
/** | |
* Solution: Add all increasing pairs. | |
* | |
* Myway: 5 7 9 3 6 4 (5,9) (3,6) only prices[i+1] < prices[i] add profit to result; but it's meaningless. | |
* just add (5,7) (7,9) (3,6) make it easy | |
* | |
*/ | |
public int maxProfit2(int[] prices) { | |
if (prices == null || prices.length == 0) { | |
return 0; | |
} | |
int profit = 0; | |
for (int i = 0; i < prices.length - 1; i++) { | |
int signleProfit = prices[i + 1] - prices[i]; | |
if (signleProfit > 0) { | |
profit += signleProfit; | |
} | |
} | |
return profit; | |
} | |
// Stock I : Brute Force O(n^2) Time Limit Exceeded -- Wrong. sale at highest first, and buy at lowest are not accepted. | |
// Arrays.sort(prices). return prices[length - 1] - prices[0] also doesn't work. | |
// My mistake: (highest, lowest) doesn't mean profit! | |
public int maxProfitWrongWay(int[] prices) { | |
if (prices == null || prices.length == 0) { | |
return 0; | |
} | |
int result = Integer.MIN_VALUE; | |
for (int i = 0; i < prices.length; i++) { | |
for (int j = 0; j < prices.length; j++) { | |
result = Math.max(result, Math.abs(prices[i] - prices[j])); | |
} | |
} | |
return result; | |
} | |
} |