leetcode_[python/C++]_121/122/123/188.Best Time to Buy and Sell Stock I/II/III/IV
2016-11-21 20:49
721 查看
121. Best Time to Buy and Sell Stock
[题目]
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.
122. Best Time to Buy and Sell Stock II
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 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).
123. Best Time to Buy and Sell Stock III
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).
188. Best Time to Buy and Sell Stock IV
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 k transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
[分析]
首先这四道题是类似的题型,逐步深入
第一道题:求一次买入卖出的最大收益
第二道题:可以买入卖出任意多次,求最大收益
第三道题:限制买入卖出次数最多为2次,求最大收益
第四道题:限制买入卖出次数最多为k次,求最大收益
第一道题:
解法1:
解法2:
或者:
解法3(动态规划):
注:第三种解法效率最高
第二道题:
解法1:
从前往后(python):
从前往后(C++):
从前往后2(C++):
解法2:
从后往前:
两种思路都是O(n) time O(1) space,效率一样
第三道题:
思路:
找出从0到i的最大收益profit[i]
找出从i到size-1的最大收益profit[i]
之和求最大值
解法1:
O(2n) time O(1) space
解法2:
O(n) time O(1) space
注:这两种解法效率相当
第四道题:
这道题有一个注意的地方就是当k>=prices.size()/2时候,证明我们可以随意买入卖出,直接累加即可
解法1:
O(kn) space O(n) time
解法2:
O(kn) space O(n) time
动态规划(比上面的快一点)
解法3:
O(n) space O(n) time
比上面的快点
解法4:
网上的一种解法,利用heap,stack
O(klogn)time ( 最快 )
贴出来一起学习
总结:这四道题虽然不断变化,但是基本的思想是一致的,而且,基本都是能够O(n) time的解法解决
[题目]
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.
122. Best Time to Buy and Sell Stock II
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 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).
123. Best Time to Buy and Sell Stock III
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).
188. Best Time to Buy and Sell Stock IV
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 k transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
[分析]
首先这四道题是类似的题型,逐步深入
第一道题:求一次买入卖出的最大收益
第二道题:可以买入卖出任意多次,求最大收益
第三道题:限制买入卖出次数最多为2次,求最大收益
第四道题:限制买入卖出次数最多为k次,求最大收益
第一道题:
解法1:
int maxProfit(vector<int>& prices) { int size = prices.size(); if(size == 0) return 0; int low = prices[0]; int high = prices[0]; int temp_low=low; for(int i=1;i<size;i++) { if(prices[i]-temp_low>=high-low) { low = temp_low; high = prices[i]; } else if(prices[i]>high) high = prices[i]; else if(prices[i]<=low) { if(prices[i]<=temp_low) temp_low = prices[i]; } } if(high-low<=0) return 0; else return high - low; }
解法2:
int maxProfit(vector<int> &prices) { int maxPro = 0; int minPrice = INT_MAX; for(int i = 0; i < prices.size(); i++){ minPrice = min(minPrice, prices[i]); maxPro = max(maxPro, prices[i] - minPrice); } return maxPro; }
或者:
int maxProfit(vector<int>& prices) { int minPrice = INT_MAX; int maxProfit = 0; for (int currPrice : prices){ if (currPrice < minPrice) minPrice = currPrice; else maxProfit = max(currPrice - minPrice, maxProfit); } return maxProfit; }
解法3(动态规划):
int maxProfit(vector<int>& prices) { int Nsize = prices.size(); int sumCurrent = 0; int sumIncrease = 0; for(int i = 1; i < Nsize; i++) { sumIncrease = sumIncrease + prices[i] - prices[i-1]; if(sumIncrease > sumCurrent) sumCurrent = sumIncrease; if(sumIncrease < 0) sumIncrease = 0; } return sumCurrent; }
注:第三种解法效率最高
第二道题:
解法1:
从前往后(python):
def maxProfit(self, prices): return sum(max(prices[i + 1] - prices[i], 0) for i in range(len(prices) - 1))
从前往后(C++):
int maxProfit(vector<int>& prices) { int size = prices.size(); if ( size == 0 || size == 1 ) return 0; int low = prices[0] , max_profit = 0; for ( int p : prices ){ if ( p > low ) max_profit += p - low; low = p; } return max_profit; }
从前往后2(C++):
int maxProfit(vector<int>& prices) { if ( prices.size() == 0 ) return 0; int max_profit = 0; for ( int i = 0 ; i < prices.size() - 1 ; i ++ ){ max_profit += prices[i+1] > prices[i] ? prices[i+1] - prices[i] : 0; } return max_profit; }
解法2:
从后往前:
int maxProfit(vector<int>& prices) { int size = prices.size(); if ( size == 0 || size == 1 ) return 0; int high = prices[size - 1] , max_profit = 0; for ( int i = size - 2 ; i >= 0 ; i -- ){ if ( prices[i] > prices[i+1] ){ max_profit += high - prices[i+1]; high = prices[i]; } } if ( prices[0] < high ) max_profit += high - prices[0]; return max_profit; }
两种思路都是O(n) time O(1) space,效率一样
第三道题:
思路:
找出从0到i的最大收益profit[i]
找出从i到size-1的最大收益profit[i]
之和求最大值
解法1:
O(2n) time O(1) space
int maxProfit(vector<int>& prices) { int size = prices.size(); if( size <= 1 ) return 0; int profit[size]; memset(profit,0,sizeof(profit)); int max_profit = 0; int Mins = prices[0]; for( int i = 1 ; i < size ; i ++ ){ if( prices[i] - Mins > max_profit ) max_profit = prices[i] - Mins; if( prices[i] < Mins ) Mins = prices[i]; profit[i] = max_profit; } int max_profit_r = 0; int Maxs = prices[size - 1] ; for( int i = size - 1 ; i >= 0 ; i-- ){ if( profit[i] + Maxs - prices[i] > max_profit_r ) max_profit_r = profit[i] + Maxs - prices[i]; if( Maxs < prices[i] ) Maxs = prices[i]; } return max_profit_r; }
解法2:
O(n) time O(1) space
int maxProfit(vector<int>& prices) { int size = prices.size(); if( size <= 1 ) return 0; int sel_1 = 0 , sel_2 = 0; int buy_1 = -prices[0], buy_2 = -prices[0]; int profit = 0 ; for( int i = 0 ; i < size ; i ++ ) { int last_sel = sel_1; sel_1 = max( sel_1 , prices[i] + buy_1 ); buy_1 = max( -prices[i] , buy_1 ); sel_2 = max( sel_2 , prices[i] + buy_2 ); buy_2 = max( last_sel - prices[i] , buy_2 ); profit = max( sel_1 , sel_2 ); } return profit; }
注:这两种解法效率相当
第四道题:
这道题有一个注意的地方就是当k>=prices.size()/2时候,证明我们可以随意买入卖出,直接累加即可
解法1:
O(kn) space O(n) time
int maxProfit(int k, vector<int>& prices) { // f[k, ii] represents the max profit up until prices[ii] (Note: NOT ending with prices[ii]) using at most k transactions. // f[k, ii] = max(f[k, ii-1], prices[ii] - prices[jj] + f[k-1, jj]) { jj in range of [0, ii-1] } // = max(f[k, ii-1], prices[ii] + max(f[k-1, jj] - prices[jj])) // f[0, ii] = 0; 0 times transation makes 0 profit // f[k, 0] = 0; if there is only one price data point you can't make any money no matter how many times you can trade if (prices.size() <= 1) return 0; if ( k > prices.size()/2 ){ int max_profit = 0; for( int i = 1 ; i < prices.size() ; i ++ ){ max_profit += max( prices[i] - prices[i-1] , 0 ); } return max_profit; } else { int maxProf = 0; vector<vector<int>> f(k+1, vector<int>(prices.size(), 0)); for (int kk = 1; kk <= k; kk++) { int tmpMax = f[kk-1][0] - prices[0]; for (int ii = 1; ii < prices.size(); ii++) { f[kk][ii] = max(f[kk][ii-1], prices[ii] + tmpMax); tmpMax = max(tmpMax, f[kk-1][ii] - prices[ii]); maxProf = max(f[kk][ii], maxProf); } } return maxProf; } }
解法2:
O(kn) space O(n) time
动态规划(比上面的快一点)
int maxProfit(int k, vector<int>& prices) { int n = prices.size(); if(k == 0 || n <= 1){ return 0; } if (k >= n/2) { int maxPro = 0; for (int i = 1; i < n; i++) { if (prices[i] > prices[i-1]) maxPro += prices[i] - prices[i-1]; } return maxPro; } vector<vector<int>> dp(k + 1, vector<int>(n + 1, 0)); for(int i = 1; i <= k; ++i){ int tmpMax = dp[i - 1][0] - prices[0]; for(int j = 1; j <= n; ++j){ dp[i][j] = max(dp[i][j - 1], tmpMax + prices[j - 1]); tmpMax = max(tmpMax, dp[i - 1][j - 1] - prices[j - 1]); } } return dp[k] ; }
解法3:
O(n) space O(n) time
比上面的快点
int maxProfit(int k, vector<int>& prices) { int n = prices.size(); if (k>=n/2) { int sum = 0; for(int i=1; i<n; i++){ if(prices[i] > prices[i-1]){ sum += prices[i] - prices[i-1]; } } return sum; } vector<int> buy(k+1, INT_MIN), sale(k+1, 0); for(int i=0; i<n; i++){ for(int j=1; j<=k; j++){ buy[j] = max(buy[j], sale[j-1]-prices[i]); sale[j] = max(sale[j], buy[j] + prices[i]); } } return sale[k]; }
解法4:
网上的一种解法,利用heap,stack
O(klogn)time ( 最快 )
贴出来一起学习
int maxProfit(int k, vector<int>& prices) { // Step 1: Find out all profit opportunities vector<int> profits; stack<pair<int, int>> vps; // valley-peak pairs int v; int p = -1; for (;;) { // find next valley-peak pair for (v = p+1; (v+1 < prices.size()) && (prices[v] >= prices[v+1]); ++v); for (p = v ; (p+1 < prices.size()) && (prices[p] <= prices[p+1]); ++p); if (v == p) { // v==p means that both v and p reach the end of the array break; } // Consider two transactions (v1, p1) (back of the stack) and (v2, p2) (the new-found). // If prices[v1] >= prices[v2], // it is meaningless to combine the two transactions. // Save of profit of (v1, p1), and pop it out of the record. while ((!vps.empty()) && (prices[v] <= prices[vps.top().first])) { profits.push_back(prices[vps.top().second] - prices[vps.top().first]); vps.pop(); } // If prices[v1]<prices[v2] and prices[p1]<prices[p2], // then it is meaningful to combine the two transactions // update (v1, p1) to (v1, p2), and save the profit of (v2, p1) while ((!vps.empty()) && (prices[p] >= prices[vps.top().second])) { profits.push_back(prices[vps.top().second] - prices[v]); v = vps.top().first; vps.pop(); } // save the new-found valley-peak pair vps.emplace(v, p); } // save all remaining profits while (!vps.empty()) { profits.push_back(prices[vps.top().second] - prices[vps.top().first]); vps.pop(); } // Step 2: Calculate the k highest profits int ret; if (profits.size() <= k) { ret = accumulate(profits.begin(), profits.end(), 0); } else { nth_element(profits.begin(), profits.end() - k, profits.end()); ret = accumulate(profits.end() - k, profits.end(), 0); } return ret; }
总结:这四道题虽然不断变化,但是基本的思想是一致的,而且,基本都是能够O(n) time的解法解决
相关文章推荐
- leetcode(121)(122)(123)(188) Best Time to Buy and Sell Stock I/II/III/IV JAVA代码
- LeetCode 121, 122, 123. Best Time to Buy and Sell Stock i, ii, iii
- 121~123 188 Best Time to Buy and Sell StockI II III IV
- LeetCode 121、122、123、188:Best Time to Buy and Sell Stock
- leetcode【121+122+123 best time to buy and sell stock】【python】
- LeetCode 121-123 Best Time to Buy and Sell Stock I II III
- 121 122 123 188 Best Time to Buy and Sell Stock
- 188. Best Time to Buy and Sell Stock IV Leetcode Python
- 【LeetCode】 Best Time to Buy and Sell Stock I II III IV 解题报告
- [LeetCode] Best Time to Buy and Sell Stock I II III IV 股票买卖
- [Leetcode] Best Time to Buy and Sell Stock I,II,III,IV
- 第一周:( LeetCode ) Best Time to Buy and Sell Stock I II III(c++)
- leetcode 121 122 123 . Best Time to Buy and Sell Stock
- LeetCode-Best Time to Buy and Sell Stock I II III IV
- 【LeetCode】 best-time-to-buy-and-sell-stock-i ii iii iv
- LeetCode - 123. Best Time to Buy and Sell Stock III - 思路详解 - C++
- Leetcode_best-time-to-buy-and-sell-stock-ii(c++ and python version)
- 【LeetCode】 Best Time to Buy and Sell Stock I II III IV 解题报告
- [LeetCode]题解(python):123-Best Time to Buy and Sell Stock III
- [LeetCode]题解(python):122-Best Time to Buy and Sell Stock II