Copyright © 直通硅谷
http://www.zhitongguigu.com/
Say you have an array for which the ith element is the price of a given stock on day 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.
Example 1:
Input: [7, 1, 5, 3, 6, 4] Output: 5 max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)
Example 2:
Input: [7, 6, 4, 3, 1] Output: 0 In this case, no transaction is done, i.e. max profit = 0.
solution 1:
dp[i] means MaxProfit in [0,1,2...i]
dp[i + 1] = max{dp[i], prices[i] - minprice }
// minprice is the lowest price in [0,1,2 ...i]
public int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE;
int maxProfit = 0;
for(int p:prices) {
minPrice = Math.min(minPrice, p);
maxProfit = Math.max(p - minPrice, maxProfit);
}
return maxProfit;
}
solution 2:
make a difference array:
prices[1] - prices[0], prices[2] - prices[0].....
prices[n-1] - prices[n-2]
=> Maximum subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.
maxSubArray(A, i) = maxSubArray(A,i-1)>0?maxSubArray(A,i-1):0 + A[i];
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.
public int maxSubArray(int[] A) {
int n = A.length;
int[] dp = new int[n];//dp[i] means the maximum subarray ending with A[i];
dp[0] = A[0];
int max = dp[0];
for(int i = 1; i < n; i++){
dp[i] = A[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
max = Math.max(max, dp[i]);
}
return max;
}
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).
Solution 1:
Find all increasing range , buy at lowest price and sell at highest price.
class Solution {
public:
int maxProfit(vector<int> &prices) {
int n = prices.size();
if(n <= 1)return 0;
int i = 0;
int res = 0;
while(i < n - 1)
{
int buy, sell;
//递减区间
while(i+1 < n && prices[i+1] < prices[i])i++;
buy = i++;
//递增区间
while(i < n && prices[i] >= prices[i-1])i++;
sell = i-1;
res += prices[sell] - prices[buy];
}
return res;
}
};
solution 2:
make a difference array:
prices[1] - prices[0], prices[2] - prices[0].....
prices[n-1] - prices[n-2]
=> Sum all positive element.
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = (int)prices.size();
int res = 0;
for(int i=1;i<n;i++){
if(prices[i]>prices[i-1]){
res +=(prices[i]-prices[i-1]);
}
}
return res;
}
int maxProfit1(vector<int>& prices) {
int n = (int)prices.size();
int res =0;
for(int i =1;i<n;i++)
{
res += (prices[i]-prices[i-1]>0?prices[i]-prices[i-1]:0);
}
return res;
}
};
Design an algorithm to find the maximum profit. You may complete at most two transactions.
solution 1: divide array into two part, find the maxProfit in each part.
*two traversal
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = (int) prices.size();
if(n==0) return 0;
vector<int> prev(n,0);
vector<int> post(n,0);
//prev traversal
int minprice = prices[0];
for(int i=1;i<n;i++){
minprice = min(prices[i],minprice);
prev[i] = max(prices[i]-minprice,prev[i-1]);
}
//post traversal
int maxprice = prices[n-1];
for(int i=n-2;i>=0;i--){
maxprice = max(prices[i],maxprice);
post[i] = max(maxprice-prices[i],post[i+1]);
}
int res = 0;
for(int i=0; i<n;i++){
res = max(res,prev[i]+post[i]);
}
return res;
}
};
solution 2:
use four variables represent your profit after executing corresponding transaction
sell2, hold2, sell1, hold1
*one traversal
public class Solution {
public int maxProfit(int[] prices) {
int hold1 = Integer.MIN_VALUE, hold2 = Integer.MIN_VALUE;
int sell1 = 0, sell2 = 0;
for(int i:prices){
// The maximum if we've just sold 2nd stock so far.
sell2 = Math.max(sell2, hold2+i);
// The maximum if we've just buy 2nd stock so far.
hold2 = Math.max(hold2, release1-i);
// The maximum if we've just sold 1nd stock so far.
sell1 = Math.max(sell1, hold1+i);
// The maximum if we've just buy 1st stock so far.
hold1 = Math.max(hold1, -i);
}
return sell2;
}
}
Design an algorithm to find the maximum profit. You may complete at most k transactions.
solution:
use 2k variables represent your profit after executing corresponding transaction
sellk, holdk, .......sell2, hold2, sell1, hold1
A simple case: == maxProfit2
2k > n // n is length of prices array
do as many operations as you can.
// Simple case.
if (k >= length / 2) {
int profit = 0;
for (int i = 1; i < length; i++) {
profit += Math.max(prices[i] - prices[i - 1], 0);
}
return profit;
}
Fill up a 2k * n form
sell k | hold k | .... | sell 1 | hold1 |
---|---|---|---|---|
Fill up a 2k form
int[] hold = new int[k + 1];
int[] sell = new int[k + 1];
Arrays.fill(hold, Integer.MIN_VALUE);
for (int price: prices) {
for (int i = 1; i <= k; i++) {
sell[i] = Math.max(sell[i], hold[i] + price);
hold[i] = Math.max(hold[i], sell[i - 1] - price);
}
}
public class Solution {
public int maxProfit(int k, int[] prices) {
int length = prices.length;
if (length < 2) return 0;
// Simple case.
if (k >= length / 2) {
int profit = 0;
for (int i = 1; i < length; i++) {
profit += Math.max(prices[i] - prices[i - 1], 0);
}
return profit;
}
// Dynamic programming.
int[] hold = new int[k + 1];
int[] sell = new int[k + 1];
Arrays.fill(hold, Integer.MIN_VALUE);
for (int price: prices) {
for (int i = 1; i <= k; i++) {
sell[i] = Math.max(sell[i], hold[i] + price);
hold[i] = Math.max(hold[i], sell[i - 1] - price);
}
}
return sell[k];
}
}
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) with the following restrictions:
Example:
prices = [1, 2, 3, 0, 2] maxProfit = 3 transactions = [buy, sell, cooldown, buy, sell]
solution 1:
//buy[i] means maxprofit when we buy stack at time i;
//sell[i] means maxprofit when we sell stack at time i;
solution 1:
//buy[i] means maxprofit when we buy stack at time i;
// buy[i] = max(sell[i-2]-prices[i],buy[i-1]+prices[i-1]-prices[i])
//sell[i] means maxprofit when we sell stack at time i;
// sell[i] = max(buy[i-1]+prices[i],sell[i-1]-prices[i-1]+prices[i])
class Solution {
public:
//buy[i] means maxprofit when we buy stack at time i;
// buy[i] = max(sell[i-2]-prices[i],buy[i-1]+prices[i-1]-prices[i])
//sell[i] means maxprofit when we sell stack at time i;
// sell[i] = max(buy[i-1]+prices[i],sell[i-1]-prices[i-1]+prices[i])
int maxProfit(vector<int>& prices) {
int n = (int)prices.size();
if(n==0)return 0;
vector<int> buy(n,0);
vector<int> sell(n,0);
buy[0] = -prices[0];
sell[0] = 0;
int res = 0;
for(int i=1;i<n;i++){
sell[i] = max(buy[i-1]+prices[i],sell[i-1]-prices[i-1]+prices[i]);
res = max(res,sell[i]);
if(i==1){
buy[i] = -prices[i];
}
else{
buy[i] = max(sell[i-2]-prices[i],buy[i-1]+prices[i-1]-prices[i]);
}
}
return res;
}
};
solution 2:
//buy[i] means Max profit till index i. The series of transaction is ending with a buy;
To make a decision whether to buy at i, we either take a rest, by just using the old decision at i - 1, or sell at/before i - 2, then buy at i, We cannot sell at i - 1, then buy at i, because of cooldown.
//sell[i] means Max profit till index i. The series of transaction is ending with a sell;
To make a decision whether to sell at i, we either take a rest, by just using the old decision at i - 1, or buy at/before i - 1, then sell at i.
solution 2:
//buy[i] means Max profit till index i. The series of transaction is ending with a buy;
buy[i] = Math.max(buy[i - 1], sell[i - 2] - prices[i]);
//sell[i] means Max profit till index i. The series of transaction is ending with a sell;
sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]);
solution 2:
//buy[i] means Max profit till index i. The series of transaction is ending with a buy;
buy[i] = Math.max(buy[i - 1], sell[i - 2] - prices[i]);
//sell[i] means Max profit till index i. The series of transaction is ending with a sell;
sell[i] = Math.max(sell[i - 1], buy[i - 1] + prices[i]);
DP solution only depending on i - 1 and i - 2 can be optimized using O(1) space.
Then arrays turn into Fibonacci like recursion:
b0 = Math.max(b1, s2 - prices[i]);
s0 = Math.max(s1, b1 + prices[i]);
public int maxProfit(int[] prices) {
if(prices == null || prices.length <= 1) return 0;
int b0 = -prices[0], b1 = b0;
int s0 = 0, s1 = 0, s2 = 0;
for(int i = 1; i < prices.length; i++) {
b0 = Math.max(b1, s2 - prices[i]);
s0 = Math.max(s1, b1 + prices[i]);
b1 = b0; s2 = s1; s1 = s0;
}
return s0;
}
solution 3: State machine:
solution 3: State machine:
s0[i] = max(s0[i - 1], s2[i - 1]); // Stay at s0, or rest from s2
s1[i] = max(s1[i - 1], s0[i - 1] - prices[i]); // Stay at s1, or buy from s0
s2[i] = s1[i - 1] + prices[i]; // Only one way from s1
find the maximum of
s0[n] and s2[n]
Base case:
s0[0] = 0; // At the start, you don't have any stock if you just rest
s1[0] = -prices[0]; // After buy, you should have -prices[0] profit. Be positive!
s2[0] = INT_MIN; // Lower base case
class Solution {
public:
int maxProfit(vector<int>& prices){
if (prices.size() <= 1) return 0;
vector<int> s0(prices.size(), 0);
vector<int> s1(prices.size(), 0);
vector<int> s2(prices.size(), 0);
s1[0] = -prices[0];
s0[0] = 0;
s2[0] = INT_MIN;
for (int i = 1; i < prices.size(); i++) {
s0[i] = max(s0[i - 1], s2[i - 1]);
s1[i] = max(s1[i - 1], s0[i - 1] - prices[i]);
s2[i] = s1[i - 1] + prices[i];
}
return max(s0[prices.size() - 1], s2[prices.size() - 1]);
}
};
int maxProfit(int[] prices) {
int sold = 0; //s2
int hold = Integer.MIN_VALUE; //s1
int rest = 0; //s0
for (int i=0; i<prices.length; ++i)
{
int prvSold = sold;
sold = hold + prices[i];
hold = Math.max(hold, rest-prices[i]);
rest = Math.max(rest, prvSold);
}
return Math.max(sold, rest);
}
class System { // assume time being used is unique
public:
int getMax() {} //O(1)
int getMin() {} //O(1)
int getRecent() {} //O(1)
void add(long time, int price) {}
void update(long time, int price) {}
void remove(long time) {}
private:
};
Get, Set, SetAll // All operation is O(1)
Get(4) -> get element at index 4
Set(index, value);
SetAll(5) -> set all element to 5
class Array{
private:
public:
Status Get(int index){}
void Set(int index, int val){}
void SetAll(int val){}
};
Copyright © 直通硅谷
http://www.zhitongguigu.com/
Copyright © 直通硅谷
http://www.zhitongguigu.com/