New Problem Solution "Best Time to Buy and Sell Stock with Transaction Fee"

This commit is contained in:
Hao Chen 2019-02-01 19:27:38 +08:00
parent 8bcae20e8a
commit eaaf7574cd
2 changed files with 202 additions and 0 deletions

View File

@ -34,6 +34,7 @@ LeetCode
|747|[Largest Number At Least Twice of Others](https://leetcode.com/problems/largest-number-at-least-twice-of-others/) | [Python](./algorithms/python/LargestNumberAtLeastTwiceOfOthers/dominantIndex.py)|Easy|
|746|[Min Cost Climbing Stairs](https://leetcode.com/problems/min-cost-climbing-stairs/) | [Python](./algorithms/python/MinCostClimbingStairs/minCostClimbingStairs.py)|Easy|
|717|[1-bit and 2-bit Characters](https://leetcode.com/problems/1-bit-and-2-bit-characters/) | [Python](./algorithms/python/1-bitAnd2-bitCharacters/isOneBitCharacter.py)|Easy|
|714|[Best Time to Buy and Sell Stock with Transaction Fee](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee) | [C++](./algorithms/cpp/bestTimeToBuyAndSellStock/BestTimeToBuyAndSellStockWithTransactionFee.cpp)|Medium|
|712|[Minimum ASCII Delete Sum for Two Strings](https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/) | [C++](./algorithms/cpp/minimumASCIIDeleteSumForTwoStrings/MinimumAsciiDeleteSumForTwoStrings.cpp)|Medium|
|687|[Longest Univalue Path](https://leetcode.com/problems/longest-univalue-path/) | [Python](./algorithms/python/LongestUnivaluePath/longestUnivaluePath.py)|Easy|
|684|[Redundant Connection](https://leetcode.com/problems/redundant-connection/) | [Python](./algorithms/python/RedundantConnection/findRedundantConnection.py)|Medium|

View File

@ -0,0 +1,201 @@
// Source : https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee
// Author : Hao Chen
// Date : 2019-02-01
/*****************************************************************************************************
*
* Your are given an array of integers prices, for which the i-th element is the price of a given
* stock on day i; and a non-negative integer fee representing a transaction fee.
*
* You may complete as many transactions as you like, but you need to pay the transaction fee for each
* transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock
* share before you buy again.)
*
* Return the maximum profit you can make.
*
* Example 1:
*
* Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
* Output: 8
*
* Explanation: The maximum profit can be achieved by:
* Buying at prices[0] = 1Selling at prices[3] = 8Buying at prices[4] = 4Selling at prices[5] = 9The
* total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
*
* Note:
* 0 < prices.length <= 50000.
* 0 < prices[i] < 50000.
* 0 <= fee < 50000.
******************************************************************************************************/
class Solution {
private:
int max(int x, int y) {
return x > y ? x: y;
}
int max(int x, int y, int z) {
return max(x, max(y,z));
}
public:
int maxProfit(vector<int>& prices, int fee) {
return maxProfit_dp03(prices, fee); // 100ms
return maxProfit_dp02(prices, fee); // 100ms
return maxProfit_dp01(prices, fee); // 2700ms
}
// find the [buy-low, sell-high] prices pairs,
// and remove the unnecessary prices.
void genPricesPairs(vector<int> &prices, vector< pair<int, int> > &prices_pairs, int fee){
int low = -1;
for (int i=0; i<prices.size()-1; i++){
//meet the valley, then goes up
if (prices[i] < prices[i+1] && low < 0 ) {
low = i;
}
//meet the peak, then goes down
if (prices[i] > prices[i+1] && low >= 0) {
prices_pairs.push_back( make_pair( prices[low], prices[i]) );
low = -1; // reset the `low` & `high`
}
}
// edge case
if ( low >= 0 ) {
prices_pairs.push_back( make_pair( prices[low], prices[prices.size()-1] ) );
}
}
int maxProfit_dp01(vector<int> &prices, int &fee) {
vector< pair<int, int> > prices_pairs;
genPricesPairs(prices, prices_pairs, fee);
vector<int> dp(prices_pairs.size()+1, 0);
for (int i=0; i<prices_pairs.size(); i++) {
for ( int j=0; j<=i; j++ ) {
int profit = prices_pairs[i].second - prices_pairs[j].first - fee;
// if the profit is negative, skip the transaction
if ( profit < 0 ) profit = 0;
dp[i+1] = max ( dp[i+1], dp[j] + profit);
}
}
return dp[dp.size()-1];
}
int maxProfit_dp02(vector<int> &prices, int &fee) {
vector< pair<int, int> > prices_pairs;
genPricesPairs(prices, prices_pairs, fee);
if ( prices_pairs.size() < 1 ) return 0;
// first - represent the max profit if we buy.
// second - represent the max profit if we sell.
vector< pair<int,int> > dp(prices_pairs.size() , make_pair(0,0) );
//buy profit - if we buy it in day 0, then we got negtive profit.
dp[0].first = - prices_pairs[0].first;
//sell profit - if we sell it in day 0, then we have the profits
// if the profit is negtive, then won't sell it.
dp[0].second = max(0, prices_pairs[0].second - prices_pairs[0].first - fee);
for (int i=1; i<prices_pairs.size(); i++) {
// BUY - we could have three options
// 1) hold the stock do nothing. profit = previous day's buy profit
// 2) sell & buy. profit = previous sell profit - spent money to buy.
// 3) fresh buy, give up the pervious buy, just buy it today.
// find the max profit of these 3 options.
dp[i].first = max (dp[i-1].first, // option 1) do nothing
dp[i-1].second - prices_pairs[i].first, // option 2) sell & buy
- prices_pairs[i].first ); // option 3) fresh buy
// SELL - we could have three options
// 1) hold the stock do nothing. profit = previous day's sell profit
// 2) sell it. profit = previous day's buy + today's sell.
// 3) sell previous and sell today. profit = previous's sell + today's sell
// Find the max profit of these 3 options
dp[i].second = max(dp[i-1].second,
dp[i-1].first + prices_pairs[i].second - fee,
dp[i-1].second + prices_pairs[i].second - prices_pairs[i].first - fee );
}
return max( dp[dp.size()-1].second, 0 );
}
//
// Actually, by given any day, we can have two status:
// 1) BUY status - we can have two options at Day X.
// i) buy stock - need previous sell status.(you cannot buy if you haven't sold)
// ii) do nothing - need previous buy status.
//
// 2) SELL status - we can have two options at Day X.
// i) sell stock - need previous buy status.(you cannot sell if you haven't bought)
// ii) do nothing - keep the previous sell status.
//
// For example:
//
// if we have [1,3,2,8,4,9], fee = 2
// then we could have the following BUY & SELL status
//
// Day One
// 1 - BUY: the profit is -1 ,becuase we spent 1 money
// SELL: you cannot sell, the profit is 0.
// Day Two
// 3 - BUY : pre-SELL - 3 = -3, but do nothing has max profit pre-BUY: -1
// SELL: pre-BUY + 3 -2 = -1+3-2 = 0 , the max profit: 0
// Day Three
// 2 - BUY : pre-SELL - 2 = 0 - 2 = -2, do nothing has max profit: -1
// SELL: pre-BUY + 2 -2 = -1 + 2 -2 = -1, do nothing has max profit: 0
// Day Four
// 8 - BUY : pre-SELL - 8 = 0 - 8 = -8, so, just hold, the max buy profit: -1
// SELL: pre-BUY + 8 - 2 = -1+8-2 =5, the max profit is 5
// Day Five
// 4 - BUY : pre-SELL - 4 = 5-4 = 1, do nothing profit is -1, so should buy it.
// so, the max buy profit is 1.
// SELL: pre-BUY + 4 -2 = -1 + 4 -2= 1, it's has lower profit than previous,
// so, we won't sell, the max sell profit is 5.
// Day Six
// 9 - BUY : pre-SELL - 9 = 5-9= -4, so won't buy, the max buy profit is 1.
// SELL: pre-BUY + 9 -2 = 1 + 9 -2 = 8, it's has higher profit. so we sell
//
// Let's use an table
//
// prices = 1, 3, 2, 8, 4, 9
// max buy profit = -1, -1, -1, -1, 1, 5
// max sell profit = 0, 0, 0, 5, 5, 8
//
// We can see we keep tracking the max buy and sell profit for everyday.
//
// buy[i] = max( buy[i-1], // do nothing
// sell[i-1] - prices[i] ); // sell in previous day can buy today
//
// sell[i] = max( sell[i-1], // do nothing
// buy[i-1] + prices[i] - fee ); // sell today
//
int maxProfit_dp03(vector<int> &prices, int &fee) {
int buy=-prices[0], sell=0;
int pre_buy=0, pre_sell=0;
for(auto price: prices) {
pre_buy = buy;
buy = max (sell - price, pre_buy);
pre_sell = sell;
sell = max( pre_buy + price - fee, pre_sell);
}
return sell;
}
};