首页 > 代码库 > Best Time to Buy and Sell Stock系列

Best Time to Buy and Sell Stock系列

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.

 

方法一:暴力破解,分别计算出前后量元素的的差,去最大值,时间复杂度为O(n2),代码略

方法二:设f(i) = a[i] - min{a1,a2...ai},即在第i天卖出时能获得的最大利润,那么有

f(0) = 0;

f(i-1) = a[i-1] - min{a1,a2...ai-1},min{a1,a2...ai} = min{min{a1,a2...ai-1]}, a[i]} = min{a[i-1]-f(i-1),a[i]}

so  f(i) = a[i] - min{a[i-1]-f(i-1), a[i]}

题目要求在这n天内买入卖出一次并获取最大利润,则就是在f数组中求最大值,时间复杂度为O(n)代码如下:

 

 1 class Solution { 2 public: 3     int maxProfit(vector<int> &prices) { 4         if( prices.size() < 2 ) return 0;   //如果元素个数少于2个,直接返回0 5         const int len = prices.size(); 6         int dp[len]; 7         dp[0] = 0; 8         int ans = 0; 9         for(int i=1; i<len; ++i) {10             dp[i] = prices[i] - min(prices[i], prices[i-1]-dp[i-1]);    //f(i) = a[i] - min{a[i-1]-f(i-1), a[i]}11             ans = max(ans, dp[i]);  //去dp数组中的最大元素12         }13         return ans;14     }15 };

 

方法三:设f(i)为第0天到第i天内获得的最大利润,minprice[i]为第0天到第i天的最小股票价格,那么有

f(i) = max{ f(i-1),  a[i] - minprice[i-1] },其中f(0) = 0,minprice[0] = a[0];

so 答案就是f数组中的最大值,时间复杂度为O(n),代码如下:

 1 class Solution { 2 public: 3     int maxProfit(vector<int> &prices) { 4         if( prices.size() < 2 ) return 0;   //如果元素个数少于2个,直接返回0 5         const int len = prices.size(); 6         int dp[len]; 7         dp[0] = 0; 8         int minprice = prices[0]; 9         int ans = 0;10         for(int i=1; i<len; ++i) {11             dp[i] = max( dp[i-1], prices[i]-minprice ); //f(i) = max{ f(i-1),  a[i] - minprice[i-1] }12             minprice = min( minprice, prices[i] );13             ans = max(ans, dp[i]);  //去dp数组中的最大元素14         }15         return ans;16     }17 };

方法四:知prices[0],prices[1],prices[2]...prices[n-1]来构建dv[0],dv[1]...dv[n-2],其中dv[i] = prices[i+1]-prices[i],要求在0~n-1天内获得最大利润,实质就是求在dv数列中求最大子数组之和,最大子数组之和求法请见http://www.cnblogs.com/bugfly/p/3922390.html,时间复杂度也为O(n),代码如下:

 1 class Solution { 2 public: 3     int maxProfit(vector<int> &prices) { 4         if( prices.size() < 2 ) return 0; 5         vector<int> dv( prices.size()-1, 0 );   //构建差值数组 6         for(int i=0; i<prices.size()-1; ++i) 7             dv[i] = prices[i+1] - prices[i]; 8         int sum = 0; 9         int ans = 0;10         for(int i=0; i<dv.size(); ++i) {    //求最大连续子数列和11             sum += dv[i];12             ans = max(ans, sum);13             if( sum < 0 ) sum = 0;14         }15         return ans;16     }17 };

 

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).

 

方法一:寻找每一个递增区间,每个区间的以最低价买入,最高价卖出。代码如下:
 1 class Solution { 2 public: 3     int maxProfit(vector<int> &prices) { 4         const int len = prices.size(); 5         if( len < 2 ) return 0; 6         int left = 0; 7         int ans = 0; 8         while( left < len ) { 9             int right = left+1;10             while( right < len && prices[right-1] <= prices[right] ) ++right;//寻找每个非严格递增区间,[left,right)就是一个递增区间11             ans += prices[right-1] - prices[left];  //最低价买入,最高价卖出12             left = right;13         }14         return ans;15     }16 };

方法二:使用Best Time to Buy and Sell Stock的方法四,将dv中的大于0的元素全部加起来,就是题目要求的答案,代码如下:

 

 1 class Solution { 2 public: 3     int maxProfit(vector<int> &prices) { 4         if( prices.size() < 2 ) return 0; 5         vector<int> dv(prices.size()-1, 0); 6         for(int i=0; i<dv.size(); ++i) 7             dv[i] = prices[i+1] - prices[i]; 8         int ans = 0; 9         for(int i=0; i<dv.size(); ++i)10             if( dv[i] > 0 ) ans += dv[i];11         return ans;12     }13 };

 

 

 

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).

 

设dp1[i]表示在0...i中获得的最大利润,dp2[i]表示在i...n-1中获得的最大利润,那么dp[i]就表示在0...n-1中买卖2次获得的最大利润,即dp[i] = dp1[i] + dp2[i],则要获取最大利润就是求dp数组的最大值
状态转移方程如下:
dp1[i] = max{ dp1[i-1], a[i] - minprice };
dp2[i] = max{ dp2[i+1], maxprice - a[i] };
时间复杂度为O(n),代码如下:
 1 class Solution { 2 public: 3     int maxProfit(vector<int> &prices) { 4         const int len = prices.size(); 5         if( len < 2 ) return 0; 6         int dp1[len], dp2[len]; 7         dp1[0] = 0; //初始化 8         int minprice = prices[0]; 9         for(int i=1; i<len; ++i) {10             dp1[i] = max( dp1[i-1], prices[i] - minprice ); //dp1[i] = max{ dp1[i-1], a[i] - minprice };11             minprice = min( minprice, prices[i] );12         }  13         dp2[len-1] = 0; //初始化14         int maxprice = prices[len-1];15         for(int i=len-2; i>=0; --i) {16             dp2[i] = max( dp2[i+1], maxprice - prices[i] ); //dp2[i] = max{ dp2[i+1], maxprice - a[i] };17             maxprice = max( maxprice, prices[i] );18         }19         int ans = 0;20         for(int i=0; i<len; ++i)21             ans = max( ans, dp1[i]+dp2[i] );    //dp[i] = dp1[i] + dp2[i]22         return ans;23     }24 };

 

Best Time to Buy and Sell Stock系列