1-1:题目大家好,我是河海哥,专注于后端,如果可以的话,想做一名code designer而不是普通的coder,一起见证河海哥的成长,您的评论与赞是我的最大动力。
You are given an array prices where prices[i] is the price of a given stock on the ith day.
Find the maximum profit you can achieve. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times) with the following restrictions:
After you sell your stock, you cannot buy stock on the next day (i.e., cooldown one day).
Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).
Example 1:
Input: prices = [1,2,3,0,2] Output: 3 Explanation: transactions = [buy, sell, cooldown, buy, sell]
Example 2:
Input: prices = [1] Output: 0
Constraints:
1 <= prices.length <= 5000 0 <= prices[i] <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown
根据买卖股票1-4的学习,我想到了,去描述当天的状态,这边是买卖无数次,那么只需要和之前一样定下,持有股票(买入状态)和不持有股票(卖出状态),但是还有一个冷冻期,也就是卖出的后一天是不能去买入的。这个冷冻期不太好处理。他一定是持有股票的一个种情况,我就想到把持有股票分成,是不是冷冻期,于是我们就一共有3种状态:
- 当天持有股票(1)
- 当天不持有股票
- 是冷冻期(2)
- 不是冷冻期(3)
然后我就开始写代码了,并且很高兴去写各种状态转移方程,如下:
public static int maxProfit2(int[] prices) {
int n = prices.length;
// 当天持有股票状态(买入状态) - 0;
// 当天不持有股票状态
// - 是冷冻期 - 1
// - 不是冷冻期 - 2
int[][] dp = new int[n + 1][3];
dp[1][0] = -prices[0];
dp[1][1] = 0;
dp[1][2] = 0;
for (int i = 2; i < n + 1; i++) {
int price = prices[i - 1];
// 第i天持有股票=max(昨天持有,昨天不持有且不是冷冻期+今天买,昨天是冷冻期+今天买)
dp[i][0] = Math.max(Math.max(dp[i - 1][0], dp[i - 1][2] - price), dp[i - 1][1] - price);
// 第i天不持有股票且是冷冻期,说明昨天刚卖
dp[i][1] = dp[i - 1][2];
// 第i天不持有股票且不是冷冻期 = max(昨天不是冷冻期,昨天冷冻期今天不是,昨天持有股票,今天刚卖)
dp[i][2] = Math.max(Math.max(dp[i - 1][2], dp[i - 1][1]), dp[i - 1][0] + price);
}
System.out.println(Arrays.deepToString(dp));
return Math.max(Math.max(dp[n][0], dp[n][1]), dp[n][2]);
}
这里面有一个严重并且容易忽略的问题,那就是以前持有/不持有股票都是针对当天交易结束之后的最优解。我这里,交易结束之后再考虑当天是不是冷冻期应该是不妥的,应该考虑,当前交易结束之后是否会进入冷冻期(也就是明天是不是冷冻期)。看完答案之后我将我的dp状态修改为
- 当天收盘之后持有股票 - 0
- 当天收盘后不持有股票
- 即将进入冷冻期(明天是冷冻期)- 1
- 即将不进入冷冻期(明天不是冷冻期)- 2
接着只要考虑这三种状态之间的转换就可以。
1-3:代码public static int maxProfit(int[] prices) {
int n = prices.length;
// 当天持有股票状态(买入状态) - 0;
// 当天不持有股票状态
// - 即将进入冷冻期 - 1(今天卖出的,明天就是冷冻期了)
// - 即将不进入冷冻期 - 2 (当天无操作,保持卖出)
int[][] dp = new int[n + 1][3];
dp[1][0] = -prices[0];
dp[1][1] = 0;
dp[1][2] = 0;
for (int i = 2; i < n + 1; i++) {
int price = prices[i - 1];
// 第i天收盘的时候持有股票 = i-1天收盘的时候就有股票;i-1天收盘的时候即将不进入冷冻期(第i天不是冷冻期)+第i天买入了股票;如果i-1天收盘的时候进入了冷冻期(今天是冷冻期)dp[i-1][1],今天就不能买了
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][2] - price);
// 第i天收盘即将进入冷冻期 = i-1天手上有股票,第i天刚卖的
dp[i][1] = dp[i - 1][0] + price;
// 第i天收盘即将不进入冷冻期 = i-1天收盘不进入冷冻期;i-1天收盘进入冷冻期=》也就是,第i天可以是冷冻期,第i天过了就不会进入冷冻期,也就是第i+1天不会是冷冻期;
dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1]);
}
System.out.println(Arrays.deepToString(dp));
return Math.max(Math.max(dp[n][0], dp[n][1]), dp[n][2]);
}
1-4:总结
被这道题坑道了zzz,其实题目倒是不难,我主要没搞清之前股票问题的定义,是当天交易结束之后的状态,以至于,我都交易结束了我还考虑当天是不是冷冻期,有点蠢zzz,如果你有更好的意见请留下宝贵的留言,一起讨论,万分感谢。ok,河海哥,加油。变强ing。



