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

一、题目描述

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

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

在这里插入图片描述

二、解题思路

第一步:确定dp

dp[i][j] :第i天状态为j,价值为dp[i][j]

第二步:递推公式

分析一下题目,我们知道我们持股的一直在买入、卖出和冷冻期三个情况之间循环,是可以区分出来四种状态的,假设在某一天i持股存在某一种状态:

在这里插入图片描述

dp[i][0]:状态一,持股状态(买入)

dp[i][1]:状态二,未持股状态(我称它为保持卖出状态),在第i天的两天前就已经卖出了股票,且过了冷冻期,现在我保持着未持股的状态。我随时都可以买入股票。因为题目中并没有说冷冻期的第二天就一定要买入股票。

dp[i][2]:状态三,未持股状态(卖出),这种未持股状态是说我昨天刚买入的股票,今天转手就卖出去。

dp[i][3]:冷冻期

为什么状态二和状态三都是未持股状态呢?下面会详细分析一下他们的区别。

  1. dp[i][0](状态一):在i这一天是持股状态,是从两种可能的状态转移过来的:

    • 前一天就是持有股票的状态,表示:dp[i][0]=dp[i-1][0]

    • 今天刚买入的股票,这种状态又分两种情况:

      ​ 情况一:前一天是冷冻期(状态四),今天正好可以买,表示:dp[i-1][3]-prices[i]

      ​ 情况二:前一天是保持的卖出状态(状态二),表示:dp[i-1][1]-prices[i]

    dp[i][0] = Math.max(dp[i-1][0], Math.max(dp[i-1][3], dp[i-1][1])-prices[i])
    
  2. dp[i][1](状态二):保持卖出状态,上面介绍过了,它也是从两种状态转过来的:

    • 前一天就是保持卖出状态,表示:dp[i][1]=dp[i-1][1]
    • 前一天是冷冻期(状态四),今天不买入股票,依然是未持股,表示:dp[i][1]=dp[i-1][3]
    dp[i][1] = Math.max(dp[i-1][1], dp[i-1][3])
    
  3. dp[i][2](状态三):今天就是刚达到卖出状态,也就是今天卖出股票,只有一种可能:

    • ​ 昨天一定是买入的状态(状态一),今天卖出
    dp[i][2] = dp[i-1][0] + prices[i]
    
  4. dp[i][3](状态三):冷冻期,只有一种可能:

    • ​ 昨天卖出了股票(状态三)
dp[i][3] = dp[i-1][2]

综上,递推公式代码为:

dp[i][0] = Math.max(dp[i-1][0], Math.max(dp[i-1][3], dp[i-1][1])-prices[i]);
dp[i][1] = Math.max(dp[i-1][1], dp[i-1][3]);
dp[i][2] = dp[i-1][0] + prices[i];
dp[i][3] = dp[i-1][2];

三、代码演示

class Solution {
    public int maxProfit(int[] prices) {
        int n = prices.length;
        
        //特判
        if(n==0){
            return 0;
        }

        //声明dp
        int[][] dp = new int[n][4];

        //初始化dp
        dp[0][0] = -prices[0];
        
        for(int i=1; i<n; i++){
            dp[i][0] = Math.max(dp[i-1][0], Math.max(dp[i-1][3], dp[i-1][1])-prices[i]);
            dp[i][1] = Math.max(dp[i-1][1], dp[i-1][3]);
            dp[i][2] = dp[i-1][0] + prices[i];
            dp[i][3] = dp[i-1][2];
        }

        return Math.max(dp[n-1][3], Math.max(dp[n-1][1], dp[n-1][2]));
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值