每日一解 最佳买卖股票时机含冷冻期

题目 最佳买卖股票时机含冷冻期

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

示例:
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown

思路

从题库看到题目的时候,我就觉得八成是个动态规划题目,进来一看果然分毫不差。继续之前动态规划的必要思路,先想想额外的空间存什么比较好。这题还是很明确的,存收益就可以。
然后就是状态转移方程了,我在卖与不卖和冷冻期的状态变化中卡了很久,然后被点破,发现实际的状态不应该是卖不卖,买不买,而应该是另外三个状态:
持有股票,没有股票、冷冻状态。
如果结合这三个状态去获取状态转移方程,那就要简单多了。比如持有股票可以通过卖股票进入冷冻状态,或者不卖股票继续保持持有状态。没有股票可以通过买股票进入持有股票状态,或者不买,保持没有股票状态。冷冻状态则只能变为没有股票状态。
用表格来说明就是:

天数12……n
持有股票0-第1天股价max(第1天持有股票,第1天没有股票-第2天股价)max(第n-1天持有股票,第n-1天没有股票-第n天股价)
没有股票0max(第1天没有股票,第1天冻结状态)max(第n-1天没有股票,第n-1天冻结状态)
冻结状态0第1天持有股票+第2天股价第n-1天持有股票+第n天股价

我自己计算状态的时候还在冷冻状态的取值时没必要地愣神了一段时间。但要注意的是,可以不考虑最后一天持有股票的收益,因为持有股票必然比不持有的状态收益低,从表格的公式里也不难证明这一点,所以最终求最大收益的时候,从没有股票和冻结状态中选最大值即可。

代码实现

代码实现的时候有一个小优化,因为每一列的3个值其实是只根据前一列的3个数据得到,其实可以不用数组来存储,只要三个数来存储其实就足够用了。

class Solution {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) {
			return 0;
		}
		int dp_map_a, dp_map_b, dp_map_c;
		//按照表格的来, dp_map_a为持有股票, dp_map_b为没有股票, dp_map_c为冻结状态。
		dp_map_a = 0 - prices[0];
		dp_map_b = 0;
		dp_map_c = 0;

		for (int i = 1; i < prices.size(); i++) {
			int new_dp_map_a = max(dp_map_a, dp_map_b - prices[i]);
			dp_map_b = max(dp_map_b, dp_map_c);
			dp_map_c = dp_map_a + prices[i];
			dp_map_a = new_dp_map_a;
		}
		return max(dp_map_b, dp_map_c);
	}
};

然后我发现尽管将内存消耗优化到了O(1),但是内存结果仍然只有十几个百分点,真是感觉很奇怪的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值