题目解析
本文是一篇题解分享,对应题目是AI刷题板块的中等题-《股票市场交易策略优化》。 问题简述如下:
给定一个数组,数组中的第 i 个元素代表第 i 天的股票价格。小R可以在市场上进行股票交易,设计一个算法来实现最大利润。
股票交易规则如下:
- 小R可以多次买卖股票,但在买入新的股票前必须卖出之前的股票。
- 每次卖出股票后存在一天的冷冻期,在冷冻期内小R不能购买股票。
思路分析
小R每天能获得的总收益与前一天的交易情况相关,因此当前题目可以划归为动态规划的范畴。小R每天(指当天最后一秒结束前的情况)收益情况与前一天的关系如下:
- 当天持有股票,说明前一天也是持有股票,或者正好是当天买入
- 当天卖出股票
- 当天不持有股票,且不是当天卖出
代码逻辑
根据前文的分析,可以构建二维数组如下
// 当天持有股票
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][2] - stocks[i]);
// 当天卖出股票
dp[i][1] = dp[i - 1][0] + stocks[i];
// 当天不持有股票,且不是当天卖出
dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1]);
- 如果当天持有股票,那么当天的最大收益应该取前一天持有股票和当天买入股票的最大值
- 如果当天不持有股票,则有两种情况
- 当天卖出,则直接计算前一天持有且今天卖出的值
- 不是当天卖出,需要判断前一天卖出,或者前一天既不持有也不卖出的最大值
完整代码
完整的代码逻辑如下
public static int solution(int[] stocks) {
int[][] dp = new int[stocks.length][3];
dp[0][0] = -stocks[0];
dp[0][1] = 0;
dp[0][2] = 0;
for(int i = 1; i < stocks.length; i++){
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][2] - stocks[i]);
dp[i][1] = dp[i - 1][0] + stocks[i];
dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1]);
}
return Math.max(dp[stocks.length - 1][0], Math.max(dp[stocks.length - 1][1], dp[stocks.length - 1][2]));
}
知识总结
这道题目是一道典型的动态规划题目,关键在于如何划分状态以及确定状态转移方程。
动态规划是一种算法设计技术,通常用于解决具有重叠子问题和最优子结构性质的问题。动态规划的核心思想是将复杂问题分解为更小的子问题,并通过存储子问题的解来避免重复计算,从而提高算法的效率。
要解决动态规划问题,需要确定问题的状态表示并确定问题的状态表示,即确定状态转移方程。这部分的内容需要经过多次练习才能有自己的做题思路。
学习计划
动态规划类的题目难度一般属于中等或者困难。通常需要对情况进行分类,应对这类题目最好的方法是先多看题解和讲解视频,然后到刷题网站中练习,通过刷题总结这类题目的规律,并将其抽象出常见的特征和做题思路。
这类题目比较典型的有如下
- 爬楼梯
- 不同路径
- 零钱兑换
- 打家劫舍
- 买卖股票最佳时机 等
工具运用
- 刷题网站:leetocde / 牛客 / 稀土掘金AI刷题等
- 视频/博客:代码随想录 / 灵茶山艾府等
- AI:豆包Marscode AI等