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

Example 1:

Input: [7, 1, 5, 3, 6, 4]
Output: 5

max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)

Example 2:

Input: [7, 6, 4, 3, 1]
Output: 0

In this case, no transaction is done, i.e. max profit = 0.
题意是:给一个数组,元素是按时间先后顺序给出每天的股票价格,只能进行一笔交易,求最大利润。

首先就想到了 n^2 的方法,果然超时了。。。

参考了别人的思路,如下:

递归求解,数组第一个元素下标begin,最后一个元素下标 end ,每次找到到前数组中最大值下标maxloc、最小值下标minloc,如果最大值位于最小值后面,直接返回prices[maxloc] - prices[minloc] 结果就是最大利润,否则算出 begin~maxloc-1 中最小值lmin,计算左段利润 prices[maxloc] - lmin;minloc~end 中最大值rmax,计算右段利润 lmax - prices[minloc] ,递归计算 maxloc+1~minloc-1端最大利润,这三段中最大利润就是结果。

原理很简单,如果maxloc<minloc,那么这段时间的价格肯定位于 prices[minloc] ~ prices[maxloc] 中,前半段最大利润和后半段最大利润都与此段时间值无关了,只与最大值、最小值有关;代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
		if(prices.empty())
			return 0;
		int begin = 0, end = prices.size()-1;
		return getMaxProfile(prices, begin, end);
	}
	int getMaxProfile(vector<int>& prices, int begin, int end)
	{
		if(begin >= end)
			return 0;
		int minval = prices[begin], maxval = prices[begin];
		int minloc = begin, maxloc = begin;
		for(int i=begin; i<=end; ++i)
		{
			if(prices[i] < minval)
			{
				minval = prices[i];
				minloc = i;
			}
			if(prices[i] > maxval)
			{
				maxval = prices[i];
				maxloc = i;
			}
		}
		if(minloc < maxloc)//低买高出
			return maxval - minval;
		else//maxloc < minloc
		{
			int lval, mval, rval;
			int lmin = prices[begin], rmax = prices[minloc];
			int lminloc = begin, rmaxloc = minloc;
			for(int i=begin; i<maxloc; ++i)
			{
				if(prices[i] < lmin)
				{
					lmin = prices[i];
					lminloc = i;
				}
			}
			lval = maxval - lmin;
			for(int i=minloc+1; i<=end; ++i)
			{
				if(prices[i] > rmax)
				{
					rmax = prices[i];
					rmaxloc = i;
				}
			}
			rval = rmax - minval;
			mval = getMaxProfile(prices, maxloc+1, minloc-1);
			return max(max(lval, mval), rval);
		}
	}
};

有一个更为简洁的方法,思路是:用一个值记录当前最小价格,顺序访问数组节点,每次计算当前价格减去最小价格值,记录当前最大差价,并更新当前最小价格,这样顺序遍历一遍就ok了。

代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
		if(prices.empty())
			return 0;
		int curlow = prices[0];
		int profile = 0, curprofile;
		for(int i=1; i<prices.size(); ++i)
		{
			curprofile = prices[i] - curlow;
			if(curprofile > profile)
				profile = curprofile;
			if(prices[i]<curlow)
				curlow = prices[i];
		}
		return profile;
	}
};


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

此题题意是:可以多次买卖,但是先买后卖,一次也只能买卖一个股票。所以就要找每个波谷,然后找该波谷对应的波峰,每次计算所有“ 波峰 - 波谷 ”和。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
		if(prices.empty())
			return 0;
        int profile = 0;
		int low = 0, high = 0;
		while(low < prices.size()-1)
		{
			for(int i=low+1; i<prices.size()-1; ++i)
				if(prices[i]<prices[low])
					low = i;
				else
					break;
			high = low+1;//"low < prices.size()-1"保证high不越界,但是要处理high为*prices.end()时特殊情况,因为此时high不一定比low大
			for(int j=high+1; j<prices.size(); ++j)
				if(prices[j]>prices[high])
					high = j;
				else
					break;
			if(prices[high] > prices[low])//处理high为*prices.end()时特殊情况,因为此时high不一定比low大
				profile += prices[high] - prices[low];
			low = high+1;
		}
		return profile;
    }
};

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

此题题意是最多只能进行两次交易,即将数组分两段,求两段获得最大利益和。

思路是前两题的结合,根据122题得到所有“波谷、波峰”数组(此步骤可处理存在大量降序数据段的情况,节省时间,当然没有此段也可得到正确结果,但是会超时),然后利用121题中,计算以0~n-1个节点将数组划分两段,两段获得最大利润之和,求得最大利润和即可。

代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
		if(prices.empty())
			return 0;
        int profile = 0;
		int low = 0, high = 0;
		vector<int>Tmp;
		while(low < prices.size()-1)
		{
			for(int i=low+1; i<prices.size()-1; ++i)
				if(prices[i]<prices[low])
					low = i;
				else
					break;
			high = low+1;//"low < prices.size()-1"保证high不越界,但是要处理high为*prices.end()时特殊情况,因为此时high不一定比low大
			for(int j=high+1; j<prices.size(); ++j)
				if(prices[j]>prices[high])
					high = j;
				else
					break;
			if(prices[high] > prices[low])//处理high为*prices.end()时特殊情况,因为此时high不一定比low大
			{
				Tmp.push_back(prices[low]);
				Tmp.push_back(prices[high]);
			}
			low = high+1;
		}
		int tmpProfile;
		for(int i=0; i<Tmp.size(); ++i)
		{
			tmpProfile = partMaxProfit(Tmp, 0, i) + partMaxProfit(Tmp, i, Tmp.size()-1);
			if(tmpProfile > profile)
				profile = tmpProfile;
		}
		return profile;
	}
    int partMaxProfit(vector<int>& prices, int begin, int end) {
		if(prices.empty())
			return 0;
		int curlow = prices[begin];
		int profile = 0, curprofile;
		for(int i=begin+1; i<=end; ++i)
		{
			curprofile = prices[i] - curlow;
			if(curprofile > profile)
				profile = curprofile;
			if(prices[i]<curlow)
				curlow = prices[i];
		}
		return profile;
	}
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值