题目描述
给定一个整数数组prices
,其中第 prices[i]
表示第 i
天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: prices = [1,2,3,0,2] 输出: 3 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
示例 2:
输入: prices = [1] 输出: 0
提示:
1 <= prices.length <= 5000
0 <= prices[i] <= 1000
解题思路
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty()) {
return 0;
}
int n = prices.size();
// f[i][0]: 今天收盘时,手上持有股票
// f[i][1]: 今天收盘时,手上未持股票,且股票今天出售
// f[i][2]: 今天收盘时,手上未持股票,且股票不是今天出售
vector<vector<int>> dp(n, vector<int>(3));
dp[0][0] = -prices[0];
for (int i = 1; i < n; i++) {
// 昨天持有股票,今天继续持有;或者昨天前已出售,今天买入
dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i]);
// 昨天持有股票,今天出售;
dp[i][1] = dp[i - 1][0] + prices[i];
// 昨天出售股票;或者昨天前已出售
dp[i][2] = max(dp[i - 1][1], dp[i - 1][2]);
}
return max(dp[n - 1][1], dp[n - 1][2]);
}
};
动态规划状态定义
dp[i][j]
表示第 i
天结束时的最大利润,其中 j
有三种状态:
dp[i][0]
: 第i
天结束时持有股票的最大利润。dp[i][1]
: 第i
天结束时刚卖出股票的最大利润。dp[i][2]
: 第i
天结束时不持有股票(并且没有在当天卖出)的最大利润。
初始状态
dp[0][0]
初始化为-prices[0]
,因为第一天买入股票花费了prices[0]
。dp[0][1]
和dp[0][2]
可以初始化为0
,因为第一天不可能卖出股票。
状态转移方程
dp[i][0]
: 第i
天持有股票可能是继续持有前一天的股票,或者是第i
天买入股票(前一天不持有股票),取这两种情况的较大值。
dp[i][1]
: 如果第i
天卖出股票,那么第i-1
天一定是持有股票的状态。
dp[i][2]
: 第i
天如果不持有股票,可能是保持前一天卖出股票的状态,或者是继续不持有股票的状态,取较大值。
最终结果
在所有交易日结束后,持有股票的利润不能算作最大利润,因此我们只需要在不持有股票的状态中找最大值。