问题描述
小R近期表现出色,公司决定以股票的形式给予奖励,并允许他在市场上进行交易以最大化收益。给定一个数组,数组中的第 i 个元素代表第 i 天的股票价格。小R需要设计一个算法来实现最大利润。
股票交易规则如下:
- 小R可以多次买卖股票,但在买入新的股票前必须卖出之前的股票。
- 每次卖出股票后存在一天的冷冻期,在冷冻期内小R不能购买股票。
你的任务是帮助小R计算出在遵守交易规则的情况下能够获得的最大利润。
stocks: 一个整数列表,表示连续几天内的股票价格。
让我们来拆解这个问题。为了实现最大利润,我们需要定义相关变量,大致需要考虑以下几点:
-
状态定义:
hold[i]:在第i天持有股票时的最大利润。sold[i]:在第i天卖出股票后的最大利润。rest[i]:在第i天处于冷冻期(即不能买入股票)时的最大利润。
-
状态转移:
hold[i]可以从hold[i-1](继续持有)或rest[i-1] - stocks[i](买入股票)转移而来。sold[i]只能从hold[i-1] + stocks[i](卖出股票)转移而来。rest[i]可以从rest[i-1](继续冷冻)或sold[i-1](冷冻期)转移而来。
-
初始状态:
hold[0]初始化为-stocks[0](买入第一天的股票)。sold[0]和rest[0]初始化为0。
-
最终结果:
- 最终的最大利润应该是
sold[n-1]或rest[n-1]中的最大值,因为最后一天可能处于冷冻期或卖出状态。
- 最终的最大利润应该是
根据以上分析,先创建状态变量再进行状态转移,在此给出代码如下:
public class Main {
public static int solution(int[] stocks) {
if (stocks == null || stocks.length == 0) {
return 0;
}
int n = stocks.length;
int[] hold = new int[n];
int[] sold = new int[n];
int[] rest = new int[n];
// 初始化状态
hold[0] = -stocks[0];
sold[0] = 0;
rest[0] = 0;
// 状态转移
for (int i = 1; i < n; i++) {
hold[i] = Math.max(hold[i-1], rest[i-1] - stocks[i]);
sold[i] = hold[i-1] + stocks[i];
rest[i] = Math.max(rest[i-1], sold[i-1]);
}
// 最终结果
return Math.max(sold[n-1], rest[n-1]);
}
public static void main(String[] args) {
// You can add more test cases here
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[0]初始化为-stocks[0],表示在第一天买入股票。sold[0]和rest[0]初始化为0,因为没有卖出和冷冻期。
-
状态转移:
hold[i]从hold[i-1]或rest[i-1] - stocks[i]转移而来。sold[i]从hold[i-1] + stocks[i]转移而来。rest[i]从rest[i-1]或sold[i-1]转移而来。
-
最终结果:
- 返回
sold[n-1]和rest[n-1]中的最大值。
- 返回
到此,本题解答完毕。
本题考察了对数组的性质和使用,比较适合对数组进行针对性练习。