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

# 309. 最佳买卖股票时机含冷冻期 (opens new window)

# Description

Difficulty: 中等

Related Topics: 数组 (opens new window), 动态规划 (opens new window)

给定一个整数数组prices,其中第 prices[i] 表示第 _i_ 天的股票价格 。​

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

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

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

示例 1:

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

示例 2:

输入: prices = [1]
输出: 0
1
2

提示:

  • 1 <= prices.length <= 5000
  • 0 <= prices[i] <= 1000

# Solution

Language: JavaScript

状态

dp[i][0] 表示第 i 天 没有持有 股票得最大利润

dp[i][1] 表示第 i 天 持有 股票时得最大利润

状态转移方程

今天没有:可由下面两种情况转化而来

昨天出售,今天不可以买

昨天持有,今天卖出

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

今天持有:可由下面两种情况转化而来:

昨天就持有,今天没卖

前天卖出,今天购入

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

这里 i-2 是因为有冷冻期,前一天不能买,只能在 i-2 那天卖出,然后才可以买

初始状态

dp[0][0] = 0;

dp[0][1] = -price[0];

/**
 * @param {number[]} prices
 * @return {number}
 */

// let dp = Array.from(new Array(n), () => new Array(2));

var maxProfit = function(prices) {
 let len = prices.length;
 let dp = [];
 let i;
 if (prices.length <= 1) {
  return 0;
 }
 for (i = 0; i < len; i++) {
  dp[i] = [];
 }
 dp[0][0] = 0;
 dp[0][1] = -prices[0];
 dp[1][0] = Math.max(prices[1]-prices[0], 0);
 dp[1][1] = Math.max(dp[0][1], dp[0][0]-prices[1]);
 for (let i = 2; i < len; i++) {
  dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
  dp[i][1] = Math.max(dp[i-1][1], dp[i-2][0] - prices[i]);
 }
 return dp[len-1][0];
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var maxProfit = function(prices) {
 let dp = [], n = prices.length;
 if (n === 0) return 0;

 for (let i = -1; i < n; i++) dp[i] = [];
 dp[0][0] = 0;
 dp[0][1] = -prices[0];
 dp[-1][0] = 0;

 for (let i = 1; i < n; i++) {
  dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
  dp[i][1] = Math.max(dp[i-1][1], dp[i-2][0] - prices[i]);
 }

 return dp[n-1][0];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 *
 * [309] 最佳买卖股票时机含冷冻期
 */


/**
 * @param {number[]} prices
 * @return {number}
dp[最后一天][持有/未持有] = ?

[买入,卖出,冷冻期,买入,卖出] 满足最大利润条件下,尽可能地完成更多的交易
dp[3][0] = dp[2][1] dp[2][0] // 这两个不用考虑 dp[1][1] dp[1][0]
dp[3][0] = Math.max(dp[2][1] + prices[3], dp[2][0]);

dp[3][1] = dp[2][1]  dp[1][0] // 冷冻期  dp[2][0] 不需要考虑 dp[1][1]
dp[3][1] = Math.max(dp[2][1], dp[1][0] - prices[3])
(64 ms)
 */
var maxProfit = function(prices) {
 const n = prices.length;
 const dp = new Array(n).fill(0).map(() => new Array(2).fill(0));
 // -1天需要的参数
 dp[-1] = [0];
 dp[0] = [0, -prices[0]];
 // 从第一天开始
 for(let i = 1; i < n; i++) {
  dp[i][0] = Math.max(dp[i-1][1] + prices[i], dp[i-1][0]);
  dp[i][1] = Math.max(dp[i-1][1], dp[i-2][0] - prices[i]);
 }
 // 返回最后一天不持有股票
 return dp[n-1][0]
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
上次更新: 2022/8/25 下午2:49:04