题目描述
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格。设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票(即冷冻期为 1 天)。
输入格式
一个数组,表示每天的股票价格。
数据约束
- 数组长度
1 <= n <= 10000 - 每天的价格
0 <= prices[i] <= 10000
输出格式
最大的收益数值。
示例
输入样例
[1, 2]
[2, 1]
[1, 2, 3, 0, 2]
[2, 3, 4, 5, 6, 7]
[1, 6, 2, 7, 13, 2, 8]
输出样例
1
0
3
5
12
解题思路
为了计算在有冷冻期的情况下买卖股票的最大利润,我们可以使用动态规划来解决这个问题。我们需要维护三个状态变量来记录不同状态下的最大利润:
hold:持有股票的最大利润。sell:当天卖出股票的最大利润。rest:当天休息(不买卖)的最大利润。
具体的状态转移方程如下:
hold:今天持有的股票可以是昨天持有的股票,或者是昨天休息今天买入的股票。hold = max(hold, rest - prices[i])
sell:今天卖出的股票只能是昨天持有的股票。sell = hold + prices[i]
rest:今天休息可以是昨天休息,或者是昨天卖出股票。rest = max(rest, sell)
初始化
hold初始化为-prices[0],因为第一天买入股票的成本是负的。sell和rest初始化为 0,因为第一天不可能卖出股票或休息。
状态更新
我们需要在遍历价格数组的过程中不断更新这三个状态变量。
代码实现
public class Main {
public static int solution(int[] prices) {
if (prices == null || prices.length == 0) {
return 0;
}
int n = prices.length;
int hold = -prices[0]; // 第一天持有股票的成本
int sell = 0; // 第一天不可能卖出股票
int rest = 0; // 第一天不可能休息
for (int i = 1; i < n; i++) {
int prevHold = hold;
int prevSell = sell;
int prevRest = rest;
// 更新 hold 状态
hold = Math.max(prevHold, prevRest - prices[i]);
// 更新 sell 状态
sell = prevHold + prices[i];
// 更新 rest 状态
rest = Math.max(prevRest, prevSell);
}
// 最终的最大利润应该是 sell 或 rest 中的最大值
return Math.max(sell, rest);
}
public static void main(String[] args) {
// 测试用例
System.out.println(solution(new int[]{1, 2}) == 1);
System.out.println(solution(new int[]{2, 1}) == 0);
System.out.println(solution(new int[]{1, 2, 3, 0, 2}) == 3);
System.out.println(solution(new int[]{2, 3, 4, 5, 6, 7}) == 5);
System.out.println(solution(new int[]{1, 6, 2, 7, 13, 2, 8}) == 12);
}
}
代码解释
-
初始化:
hold初始化为-prices[0],因为第一天买入股票的成本是负的。sell和rest初始化为 0,因为第一天不可能卖出股票或休息。
-
状态转移:
hold:今天持有的股票可以是昨天持有的股票,或者是昨天休息今天买入的股票。Math.max(prevHold, prevRest - prices[i])。sell:今天卖出的股票只能是昨天持有的股票。prevHold + prices[i]。rest:今天休息可以是昨天休息,或者是昨天卖出股票。Math.max(prevRest, prevSell)。
-
最终结果:
- 最终的最大利润应该是
sell或rest中的最大值,因为最后一天要么卖出股票,要么休息。
- 最终的最大利润应该是
通过这种方式,我们可以有效地计算出在有冷冻期的情况下买卖股票的最大利润。