LeetCode:Buying and selling stocks II

题目描述

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例1

输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

示例2

输入: prices = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

动态规划算法

开辟一个长度与prices数组相同的二维dp数组,dp[i][0]表示当日持有股票所累积的最大利润,dp[i][1]表示当日持有股票的最大利润.设prices 长度为n,易知当最后一天不持有股票时,才能获得最大利润。因此只需求出dp[n-1][1]即可。

状态转移方程为:

i=0:

                              dp[i][0]=-prices[i]

                              dp[i][1]=0 

i>0:

                              dp[i][0] = max(dp[i - 1][0] , dp[i - 1][1] - prices[i])
                              dp[i][1] = max(dp[i - 1][0] + prices[i] , dp[i - 1][1])

C++代码

#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
	int maxProfit(vector<int>& prices)
	{
		int** dp = new int* [prices.size()];
		for (int i = 0; i < prices.size(); i++)
		{
			dp[i] = new int[2];
			dp[i][0] = 0; dp[i][1] = 0;
		}
		dp[0][0] = -prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++)
		{
			dp[i][0] = dp[i - 1][0] > dp[i - 1][1] - prices[i] ? dp[i - 1][0] : dp[i - 1][1] - prices[i];
			dp[i][1] = dp[i - 1][0] + prices[i] > dp[i - 1][1] ? dp[i - 1][0] + prices[i] : dp[i - 1][1];
		}
		return dp[prices.size() - 1][1];
	}
};
int main() {
	int n=0;
	vector<int>prices;
	while (cin >> n)
	{
		if (n == 0)break;
		prices.push_back(n);
	}
	Solution DP;
	int result = DP.maxProfit(prices);
	cout << result << endl;
}

python代码

cin=input()
temp=cin.split(' ')
dp=[]
for i in range(len(temp)):
    dp.append([0,0])
dp[0][0]=-eval(temp[0])
dp[0][1]=0
for i in range(1,len(temp)):
    dp[i][0]=max(dp[i-1][0],dp[i-1][1]-eval(temp[i]))
    dp[i][1]=max(dp[i-1][0]+eval(temp[i]),dp[i-1][1])
    print(dp[i][0],end=' ')
    print(dp[i][1])
print(dp[len(temp)-1][1])

贪心算法

当区间的值连续增大时,右端点的值减去左端点的值大于子区间的右端点值减去左端点值之和;

当区间的值不连续增大时,右端点的值减去左端点的值小于连续增大的子区间的右端点值减去左端点值之和。

因此,只需求出所有连续增大的区间的右端点值减去左端点值之和。

C++代码

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
	int maxProfit(vector<int>& prices) {
		prices.push_back(-1);
		int* profit = new int[prices.size()];
		int top = 0;
		int i = 0, j = 1;
		int sum = 0;
		while (j < prices.size())
		{
			if (prices[j - 1] < prices[j])
			{
				j++;
			}
			else
			{
				if (j - 2 < 0)
				{
					i = j;
					j++;
					continue;
				}
				if (prices[j - 1] > prices[j - 2])
				{
					sum += prices[j - 1] - prices[i];
					i = j;
					j += 1;
				}
				else
				{
					i = j;
					j += 1;
				}
			}
		}
		return sum;
	}
};
int main()
{
	Solution P;
	vector<int>prices;
	int n = 0;
	while (cin >> n)
	{
		if (n == 0)break;
		prices.push_back(n);
	}
	cout<<P.maxProfit(prices);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值