0%

leetcode每日一题-最佳买卖股票时机含冷冻期

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

image1

首先我们定义$dp[i]$表示第$i$天结束以后总的收益,因为含有冷冻期,所以我们定义三种状态:

  • $dp[i][0]$:第$i$天结束以后,持有一支股票,即当天进行买入操作或者第$i-1$天持有股票然后在第$i$天什么都没操作。
  • $dp[i][1]$:第$i$天结束以后,不持有股票,且进入冷冻期,即当天进行卖出操作。
  • $dp[i][2]$:第$i$天结束以后,不持有股票,也不进入冷冻期,即当天什么都没操作。

状态转移方程如下:

  1. 对于$dp[i][0]$,第$i$天的收益有两种情况,第一种是什么都没操作,第二种是当天进行买入操作。

$$
dp[i][0] = max(dp[i-1][0],dp[i-1][2]-prices[i])​
$$

  1. 对于$dp[i][1]$,第$i$天的收益只有一种情况,就是卖出股票。

$$
dp[i][1] = dp[i-1][0]+prices[i]
$$

  1. 对于$dp[i][2]$,第$i$天的收益有两种情况,第一种是第$i-1$天就是第三种状态,且第$i$天什么都没操作,第二种是冷冻期结束。

$$
dp[i][2] = max(dp[i-1][1],dp[i-1][2])
$$

最后的结果应该是:
$$
max(dp[n-1][0],dp[n-1][1],dp[n-1][2])
$$
实际上不用比较$dp[n-1][0]$,应该如果在最后一天还持有股票,那么显然没有任何意义,所以只需要比较$dp[n-1][1]$和$dp[n-1][2]$就可以了。

第0天的情况为边界条件:

  • $dp[0][0] = -prices[0]$
  • $dp[0][1]=0$
  • $dp[0][2]=0$
1
/*
2
 * @lc app=leetcode.cn id=309 lang=java
3
 *
4
 * [309] 最佳买卖股票时机含冷冻期
5
 */
6
7
// @lc code=start
8
class Solution {
9
    public int maxProfit(int[] prices) {
10
        if(prices.length == 0){
11
            return 0;
12
        }
13
        int n = prices.length;
14
        int[][] dp = new int[n][3];
15
        dp[0][0] = -prices[0];
16
        dp[0][1] = 0;
17
        dp[0][2] = 0;
18
        for(int i=1; i<n; i++){
19
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][2]-prices[i]);
20
            dp[i][1] = dp[i-1][0] + prices[i];
21
            dp[i][2] = Math.max(dp[i-1][1], dp[i-1][2]);
22
        }
23
        return Math.max(dp[n-1][1], dp[n-1][2]);
24
    }
25
}

复杂度分析

  • 时间复杂度:$O(n)$。
  • 空间复杂度:$O(n)$。

注意到第$i$天的状态只与第$i-1$天的状态有关,可以由此进行空间的优化。

1
/*
2
 * @lc app=leetcode.cn id=309 lang=java
3
 *
4
 * [309] 最佳买卖股票时机含冷冻期
5
 */
6
7
// @lc code=start
8
class Solution {
9
    public int maxProfit(int[] prices) {
10
        if(prices.length == 0){
11
            return 0;
12
        }
13
        int n = prices.length;
14
        int dp0 = -prices[0];
15
        int dp1 = 0;
16
        int dp2 = 0;
17
        for(int i=1; i<n; i++){
18
            int newdp0 = Math.max(dp0, dp2-prices[i]);
19
            int newdp1 = dp0 + prices[i];
20
            int newdp2 = Math.max(dp1, dp2);
21
            dp0 = newdp0;
22
            dp1 = newdp1;
23
            dp2 = newdp2;
24
        }
25
        return Math.max(dp1, dp2);
26
    }
27
}

复杂度分析

  • 时间复杂度:$O(n)$。
  • 空间复杂度:$O(1)$。