Best Time to Buy and Sell Stock I II III

Best Time to Buy and Sell Stock I II III

I
对于第一题,本质意义是求出数组中某两个元素(day[i],day[i])的最大差值。但是,要求j>i

int maxProfit(vector<int> &prices) {
        if(prices.size() ==0)
            return 0;
        
        int min=prices[0], profit=0;
        for(int i=0; i<prices.size(); i++)
        {
            if(prices[i] - min > profit)
                profit = prices[i] - min;
                
            if(prices[i] < min)
                min = prices[i];
            
            
        }
        
        return profit;
    }

II
第二题是可以进行任意多次交易,那么对数组遍历,找到临时最小值和临时最大值。
int maxProfit(vector<int> &prices) {
        if (prices.size() == 0)
		return 0;

	int profit = 0, tmpMin=prices[0], tmpMax=prices[0];
	int n = prices.size();
	for (int i = 1; i < n; i++)
	{
	    //寻找比tmpMIN小的元素
		if (prices[i] < tmpMin)
		{
		    //比tmpMin小,则更新较小的
			tmpMin = prices[i];
		}
		else
		{
		    //比tmpMin大,则可以出手卖掉,并更新tmpMin
			profit += (prices[i]-tmpMin);
			tmpMin = prices[i];
		}
	}

	return profit;
    }

III
第三题比较复杂,只允许买卖两次,有两种方法。
其一,由于两次操作之间没有交互,即第一次买卖完成之后才能进行第二次的买卖,因此可以用分治法将[0...n]中取任意一个i,分别去求[0...i]和[i+1...n-1]的最大利润,那么两者之和就是两次操作的最大利润,但是这个算法的时间复杂度是O^2,超时了。

//取[m, n]之间的最大利润
int Profit1(vector<int>& prices, int m, int n)
{
	int size = prices.size();
	if(m >= size)
		return 0;

	int minPrice = prices[m], profit = 0;
	for (int i = m+1; i < n; i++)
	{
		if (prices[i] - minPrice > profit)
		{
			profit = prices[i] - minPrice;
		}

		if (prices[i] < minPrice)
		{
			minPrice = prices[i];
		}
	}

	return profit;
}

int maxProfit(vector<int> &prices)
{
	if(prices.size() == 0)
		return 0;

	int n = prices.size();
	int max1 = 0;
	for (int i = 1; i < n; i++)
	{
		int tmp1 = Profit1(prices, 0, i);		
		int tmp2 = Profit1(prices, i+1, n);
		if(tmp1 + tmp2 > max1)
			max1 = tmp1 + tmp2;
	}

	return max1;
}

方法二,DP,参考了一位网友的方法: http://blog.youkuaiyun.com/pickless/article/details/12034365
DP的关键是找出地推关系式
int maxProfit(vector<int> &prices)
{
	int n = prices.size();
	if(0==n || 1==n)
		return 0;

	int * l = new int[n];
	int * r = new int[n];
	memset(l, 0, sizeof(int) * n);
	memset(r, 0, sizeof(int) * n);


	int minPrice = prices[0];
	for (int i = 1; i < n; i++)
	{
		l[i] = prices[i] - minPrice > l[i-1]? prices[i] - minPrice : l[i-1];
		minPrice = prices[i] < minPrice ? prices[i] : minPrice;
	}

	int maxPrice = prices[n-1];
	for (int i = n-2; i >=0; i--)
	{
		r[i] = maxPrice - prices[i] > r[i+1] ? maxPrice - prices[i] : r[i+1];
		maxPrice = prices[i] > maxPrice ? prices[i] : maxPrice;
	}

	int profit = 0;
	for (int i = 0; i < n; i++)
	{
		profit = l[i] + r[i] > profit ? l[i] + r[i] : profit;
	}

	delete l;
	delete r;

	return profit;
}





最佳的时间买卖股票III问题也可以使用动态规划算法来解决。动态规划算法通过将问题拆分为子问题,并利用子问题的解来构建更大规模问题的解。 对于最佳的时间买卖股票III问题,我们可以使用动态规划来构建一个二维数组dp,其中dp[i][j]表示在第i天结束时,最多进行j次交易所能获得的最大利润。 我们可以使用两个状态数组buysell来表示第j次交易的买入和卖出价格。初始化buysell数组为负无穷大。 接下来,我们遍历股票价格列表,对于每一天的价格,我们更新buysell数组的值。具体更新方式如下: 1. 对于第j次交易的买入价格,我们可以选择继续保持之前的买入价格(buy[j])或者在第i天买入(prices[i] - dp[i-1][j-1])。 2. 对于第j次交易的卖出价格,我们可以选择继续保持之前的卖出价格(sell[j])或者在第i天卖出(prices[i] + buy[j])。 在更新完buysell数组后,我们更新dp[i][j]为当前的最大利润(即sell[j])。 最后,我们返回dp[-1][-1]作为最大利润。 下面是使用动态规划算法解决最佳的时间买卖股票III问题的代码示例(假设prices是股票价格的列表): ```python def maxProfit(prices): n = len(prices) k = 2 # 最多进行两次交易 dp = [[0] * (k+1) for _ in range(n)] buy = [-float('inf')] * (k+1) sell = [0] * (k+1) for i in range(n): for j in range(1, k+1): buy[j] = max(buy[j], dp[i-1][j-1] - prices[i]) sell[j] = max(sell[j], prices[i] + buy[j]) dp[i][j] = max(dp[i-1][j], sell[j]) return dp[-1][-1] ``` 这个算法的时间复杂度是O(nk),其中n是股票价格列表的长度,k是最多进行的交易次数。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值