[LeetCode]Best Time to Buy and Sell Stock 系列

来源:互联网 发布:商业源码免费下载 编辑:程序博客网 时间:2024/06/10 06:20

1、Best Time to Buy and Sell Stock III

本题是Best Time to Buy and Sell Stock/的改进版。

本题中,可以买最多买进卖出两次股票。

买两次股票可以看成是第0~i天买进卖出以及第i+1~n-1天买进卖出两部分。这要枚举i并求出0th~ith的最大利益与(i+1)th~(n-1)th的最大利益之和的最大值就是买进卖出两次可以得到的最大利益。即状态转移方程:

dp[0,n-1]=max{dp[0,k]+dp[k+1,n-1]},k=1,...,n-2

而只买进卖出一次的最大利润通过0th~ith可以求得。


这里求(i+1)th~(n-1)th的最大利润可以由右向左遍历的方法实现。

class Solution {public:int maxProfit(vector<int> &p) {int n=p.size(),i,j;if(n<=1)return 0;        int *le=new int[n],*ri=new int[n];memset(le,0,sizeof(int)*n);memset(ri,0,sizeof(int)*n);int minv=p[0];for(i=1;i<n;++i){if(p[i]-minv>0)le[i]=p[i]-minv;if(le[i]<le[i-1])le[i]=le[i-1];if(minv>p[i])minv=p[i];}int maxv=p[n-1];for(i=n-2;i>=0;--i){if(maxv-p[i] >0)ri[i]=maxv-p[i];if(ri[i]<ri[i+1])ri[i]=ri[i+1];if(maxv<p[i])maxv=p[i];}maxv=le[n-1];for(i=1;i<n-2;++i){if(le[i]+ri[i+1]>maxv)maxv=le[i]+ri[i+1];}return maxv;    }};


2、Best Time to Buy and Sell Stock II

这里允许买卖多次,且允许同一天买入和卖出(如果是同一天买入卖出的话,是没有挣的,所以不能能存在这种情况)。

考虑2个例子:

5 8 7 10 

可以最大获益是5买入,8卖出,7买入,10卖出,收益为3+3=6。

这里,在8的时候卖出而不等到10的时候卖出是因为8之后这只股票降了(8->7),因此此时卖出的话可以收益多1,。

而对于5 6 7 10的例子,因为6<7,所以没有必要卖出。这里可以5->10的获利可以看成是各段获利之和。


从这两个例子可以看出,应该尽量得到当前天股票的最大值。如果第i+1天贬值了,则应该卖出。这里采用的方法就是如果当天可以获利就马上卖出,这对于上升的序列来说是不影响的,对于上升下降又上升的序列,可以获得更优的值。


class Solution {public:intmaxProfit(vector<int> &p) {       int n=p.size();       if(n<=0)return 0;              inti,ans=0;              for(i=1;i<n;++i){                     if(p[i]>p[i-1])ans+=(p[i]-p[i-1]);}return ans;    }};


按是否第i+1天贬值为依据决定是否在第i天卖掉。

class Solution {public:int maxProfit(vector<int> &p) {int n=p.size();        if(n<=0)return 0;if(n==2)return p[0]<p[1]?p[1]-p[0]:0;int i,ans=0,minv=-1;for(i=0;i<n;++i){if(minv>=0&&i<n-1&&p[i]>p[i-1]){ans+=(p[i]-p[minv]);minv=i+1;}if(minv<0||p[i]<p[minv])minv=i;}if(minv<n)ans+=(p[n-1]-p[minv]);return ans;    }};




0 0