股票市场交易策略优化
问题描述
小R近期表现出色,公司决定以股票的形式给予奖励,并允许他在市场上进行交易以最大化收益。给定一个数组,数组中的第 i 个元素代表第 i 天的股票价格。小R需要设计一个算法来实现最大利润。
股票交易规则如下:
- 小R可以多次买卖股票,但在买入新的股票前必须卖出之前的股票。
- 每次卖出股票后存在一天的冷冻期,在冷冻期内小R不能购买股票。
你的任务是帮助小R计算出在遵守交易规则的情况下能够获得的最大利润。
- stocks: 一个整数列表,表示连续几天内的股票价格。
测试样例
样例1:
输入:stocks = [1, 2]
输出:1
样例2:
输入:stocks = [2, 1]
输出:0
样例3:
输入:stocks = [1, 2, 3, 0, 2]
输出:3
样例4:
输入:stocks = [2, 3, 4, 5, 6, 7]
输出:5
样例5:
输入:stocks = [1, 6, 2, 7, 13, 2, 8]
输出:12
问题理解
我们需要计算在给定的股票价格数组中,通过多次买卖股票并遵守冷冻期规则,能够获得的 最大利润。
关键点
- 多次买卖:这意味着我们可以多次买入和卖出股票。
- 冷冻期: 每次卖出后需要等待一天才能再次买入。
数据结构与算法选择
由于我们需要考虑多次买卖和冷冻期,动态规划(DP) 是一个合适的选择。我们可以使用两个状态来表示每一天的状态:
- hold[i] :表示第 i 天持有股票时的最大利润。
- unhold[i] :表示第 i 天不持有股票时的最大利润。
状态转移方程
- 持有股票:
- 如果第 i 天持有股票,那么可能是前一天就持有股票,或者前一天不持有股票但今天买入。
- hold[i] = max(hold[i-1], unhold[i-2] - stocks[i])
- 不持有股票:
- 如果第 i 天不持有股票,那么可能是前一天就不持有股票,或者前一天持有股票但今天卖出。
- unhold[i] = max(unhold[i-1], hold[i-1] + stocks[i])
初始条件
- hold[0] = -stocks[0] :第一天买入股票。
- unhold[0] = 0:第一天不持有股票。
最终答案
最终的最大利润是不持有股票的最大值,即 unhold[n-1] ,其中 n 是股票价格数组的长度。
状态转移方程
我们有两个状态数组:
- hold[i] :表示第 i 天持有股票时的最大利润。
- unhold[i] :表示第 i 天不持有股票时的最大利润。
状态转移方程的详细解释
- 持有股票的状态转移:
- hold[i] = max(hold[i-1], unhold[i-2] - stocks[i])
- 解释:
-
- hold[i-1] :表示第 i 天继续持有前一天的股票。
- unhold[i-2] - stocks[i] :表示第 i 天买入股票。由于有冷冻期,买入股票的前提是前两天不持有股票(即 unhold[i-2] )。
- 不持有股票的状态转移:
- unhold[i] = max(unhold[i-1], hold[i-1] + stocks[i])
- 解释:
-
- unhold[i-1] :表示第 i 天继续不持有股票。
- hold[i-1] + stocks[i] :表示第 i 天卖出股票。卖出股票的前提是前一天持有股票(即 hold[i-1] )。
初始条件
- hold[0] = -stocks[0] :第一天买入股票。
- unhold[0] = 0:第一天不持有股票。
public class Main {
public static int solution(int[] stocks) {
int n = stocks.length;
if (n == 0) return 0;
int[] hold = new int[n];
int[] unhold = new int[n];
// 初始条件
hold[0] = -stocks[0];
unhold[0] = 0;
for (int i = 1; i < n; i++) {
// 持有股票的状态转移
hold[i] = Math.max(hold[i-1], (i >= 2 ? unhold[i-2] : 0) - stocks[i]);
// 不持有股票的状态转移
unhold[i] = Math.max(unhold[i-1], hold[i-1] + stocks[i]);
}
// 最终答案
return unhold[n-1];
}
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);
}
}