309. 买卖股票的最佳时机含冷冻期

文章介绍了使用动态规划解决LeetCode上买卖股票问题,考虑了冷冻期限制,通过f[i][0]、f[i][1]和f[i][2]分别表示持有、冷冻期和非冷冻期的累计最大收益,详细解释了状态转移方程并给出了简化空间的优化版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接:

309. 买卖股票的最佳时机含冷冻期

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/

完成情况:

在这里插入图片描述

解题思路:

	//卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
	/*
	很经典的dp题目。= =~

	我们用 f[i]表示第 i 天结束之后的「累计最大收益」。
    根据题目描述,由于我们最多只能同时买入(持有)一支股票,并且卖出股票后有冷冻期的限制,因此我们会有三种不同的状态:
        -我们目前持有一支股票,对应的「累计最大收益」记为 f[i][0];
        -我们目前不持有任何股票,并且处于冷冻期中,对应的「累计最大收益」记为 f[i][1];
        -我们目前不持有任何股票,并且【不处于】冷冻期中,对应的「累计最大收益」记为 f[i][2]。

    如何进行状态转移呢?在第 iii 天时,我们可以在不违反规则的前提下进行「买入」或者「卖出」操作,此时第 i天的状态会从第 i−1天的状态转移而来;我们也可以不进行任何操作,此时第 i天的状态就等同于第 i−1 天的状态。那么我们分别对这三种状态进行分析:
    ●对于 f[i][0],我们目前持有的这一支股票可以是在第 i−1天就已经持有的,对应的状态为 f[i−1][0];或者是第 i 天买入的,那么第 i−1 天就不能持有股票并且不处于冷冻期中,对应的状态为 f[i−1][2] 加上买入股票的负收益 prices[i]。因此状态转移方程为:
         f[i][0]=max(f[i−1][0],f[i−1][2]−prices[i])
    ●对于 f[i][1],我们在第 i 天结束之后处于冷冻期的原因是在当天卖出了股票,那么说明在第 i−1 天时我们必须持有一支股票,对应的状态为 f[i−1][0] 加上卖出股票的正收益 prices[i]。因此状态转移方程为:
         f[i][1]=max(f[i−1][0],f[i−1][2]−prices[i])
    ●对于 f[i][2],我们在第 i 天结束之后不持有任何股票并且不处于冷冻期,说明当天没有进行任何操作,即第 i−1 天时不持有任何股票:如果处于冷冻期,对应的状态为 f[i−1][1];如果不处于冷冻期,对应的状态为 f[i−1][2]。因此状态转移方程为:
         f[i][2]=max(f[i−1][1],f[i−1][2])

    这样我们就得到了所有的状态转移方程。如果一共有 n 天,那么最终的答案即为:
        max(f[n−1][0],f[n−1][1],f[n−1][2])

参考代码:

__309买卖股票的最佳时机含冷冻期

package 西湖算法题解___中等题;

public class __309买卖股票的最佳时机含冷冻期 {
	public int maxProfit(int[] prices) {
		//卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
		/*
		很经典的dp题目。= =~

		我们用 f[i]表示第 i 天结束之后的「累计最大收益」。
        根据题目描述,由于我们最多只能同时买入(持有)一支股票,并且卖出股票后有冷冻期的限制,因此我们会有三种不同的状态:
            -我们目前持有一支股票,对应的「累计最大收益」记为 f[i][0];
            -我们目前不持有任何股票,并且处于冷冻期中,对应的「累计最大收益」记为 f[i][1];
            -我们目前不持有任何股票,并且【不处于】冷冻期中,对应的「累计最大收益」记为 f[i][2]。

        如何进行状态转移呢?在第 iii 天时,我们可以在不违反规则的前提下进行「买入」或者「卖出」操作,此时第 i天的状态会从第 i−1天的状态转移而来;我们也可以不进行任何操作,此时第 i天的状态就等同于第 i−1 天的状态。那么我们分别对这三种状态进行分析:
        ●对于 f[i][0],我们目前持有的这一支股票可以是在第 i−1天就已经持有的,对应的状态为 f[i−1][0];或者是第 i 天买入的,那么第 i−1 天就不能持有股票并且不处于冷冻期中,对应的状态为 f[i−1][2] 加上买入股票的负收益 prices[i]。因此状态转移方程为:
             f[i][0]=max(f[i−1][0],f[i−1][2]−prices[i])
        ●对于 f[i][1],我们在第 i 天结束之后处于冷冻期的原因是在当天卖出了股票,那么说明在第 i−1 天时我们必须持有一支股票,对应的状态为 f[i−1][0] 加上卖出股票的正收益 prices[i]。因此状态转移方程为:
             f[i][1]=max(f[i−1][0],f[i−1][2]−prices[i])
        ●对于 f[i][2],我们在第 i 天结束之后不持有任何股票并且不处于冷冻期,说明当天没有进行任何操作,即第 i−1 天时不持有任何股票:如果处于冷冻期,对应的状态为 f[i−1][1];如果不处于冷冻期,对应的状态为 f[i−1][2]。因此状态转移方程为:
             f[i][2]=max(f[i−1][1],f[i−1][2])

        这样我们就得到了所有的状态转移方程。如果一共有 n 天,那么最终的答案即为:
            max(f[n−1][0],f[n−1][1],f[n−1][2])
		 */
		int n =  prices.length;
		if(n == 0){
			return 0;
		}

		int f_dp [][] = new int[n][3];
		f_dp[0][0] = -prices[0];    //我们看的是,收益,第一个你可以选择跳过,也可以选择买入,买入即为负数
		for (int i=1;i<n;i++){
			f_dp[i][0] = Math.max(f_dp[i-1][0],f_dp[i-1][2] - prices[i]);
			f_dp[i][1] = f_dp[i-1][0] + prices[i];
			f_dp[i][2] = Math.max(f_dp[i-1][1],f_dp[i-1][2]);
		}
		return Math.max(f_dp[n-1][1],f_dp[n-1][2]);
	}
}

__309买卖股票的最佳时机含冷冻期__空间优化

package 西湖算法题解___中等题;

public class __309买卖股票的最佳时机含冷冻期__空间优化 {
	public int maxProfit(int[] prices){
		//卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
		/*
		很经典的dp题目。= =~

		我们用 f[i]表示第 i 天结束之后的「累计最大收益」。
        根据题目描述,由于我们最多只能同时买入(持有)一支股票,并且卖出股票后有冷冻期的限制,因此我们会有三种不同的状态:
            -我们目前持有一支股票,对应的「累计最大收益」记为 f[i][0];
            -我们目前不持有任何股票,并且处于冷冻期中,对应的「累计最大收益」记为 f[i][1];
            -我们目前不持有任何股票,并且【不处于】冷冻期中,对应的「累计最大收益」记为 f[i][2]。

        如何进行状态转移呢?在第 iii 天时,我们可以在不违反规则的前提下进行「买入」或者「卖出」操作,此时第 i天的状态会从第 i−1天的状态转移而来;我们也可以不进行任何操作,此时第 i天的状态就等同于第 i−1 天的状态。那么我们分别对这三种状态进行分析:
        ●对于 f[i][0],我们目前持有的这一支股票可以是在第 i−1天就已经持有的,对应的状态为 f[i−1][0];或者是第 i 天买入的,那么第 i−1 天就不能持有股票并且不处于冷冻期中,对应的状态为 f[i−1][2] 加上买入股票的负收益 prices[i]。因此状态转移方程为:
             f[i][0]=max(f[i−1][0],f[i−1][2]−prices[i])
        ●对于 f[i][1],我们在第 i 天结束之后处于冷冻期的原因是在当天卖出了股票,那么说明在第 i−1 天时我们必须持有一支股票,对应的状态为 f[i−1][0] 加上卖出股票的正收益 prices[i]。因此状态转移方程为:
             f[i][1]=max(f[i−1][0],f[i−1][2]−prices[i])
        ●对于 f[i][2],我们在第 i 天结束之后不持有任何股票并且不处于冷冻期,说明当天没有进行任何操作,即第 i−1 天时不持有任何股票:如果处于冷冻期,对应的状态为 f[i−1][1];如果不处于冷冻期,对应的状态为 f[i−1][2]。因此状态转移方程为:
             f[i][2]=max(f[i−1][1],f[i−1][2])

        这样我们就得到了所有的状态转移方程。如果一共有 n 天,那么最终的答案即为:
            max(f[n−1][0],f[n−1][1],f[n−1][2])
		 */
		int n = prices.length;
		if (prices.length == 0){
			return 0;
		}
		int f0_dp = -prices[0];
		int f1_dp = 0;
		int f2_dp = 0;
		for (int i=1;i<n;i++){
			int new_f0_dp = Math.max(f0_dp,f2_dp - prices[i]);
			int new_f1_dp = f0_dp + prices[i];
			int new_f2_dp = Math.max(f1_dp,f2_dp);
			f0_dp = new_f0_dp;
			f1_dp = new_f1_dp;
			f2_dp = new_f2_dp;
		}
		return Math.max(f1_dp,f2_dp);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值