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

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;
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值