188.买卖股票的最佳时机IV
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/
文档讲解:https://programmercarl.com/0188.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4…
视频讲解:https://www.bilibili.com/video/BV16M411U7XJ
思路
将买卖股票3当中的递推公式抽象成一个循环:
- 第i天第j次交易后持有股票的两种情况
dp[i][2 * j - 1]
:- 第i - 1天第j次交易后持有股票
dp[i - 1][2 * j - 1]
; - 第i - 1天第j次交易后不持有股票,是第i天买的股票
dp[i - 1][2 * j - 2] - prices[i]
。
- 第i - 1天第j次交易后持有股票
- 第i天第j次交易后不持有股票的两种情况
dp[i][2 * j]
:- 第i - 1天第j次交易后不持有股票
dp[i][2 * j]
; - 第i - 1天第j次交易后持有股票,是第i天卖的股票
dp[i][2 * j - 1]
。
- 第i - 1天第j次交易后不持有股票
for (int j = 1; j <= k; j++) {dp[i][2 * j - 1] = Math.max(dp[i - 1][2 * j - 1], dp[i - 1][2 * j - 2] - prices[i]);dp[i][2 * j] = Math.max(dp[i - 1][2 * j], dp[i - 1][2 * j - 1] + prices[i]);
}
代码
class Solution {public int maxProfit(int k, int[] prices) {int[][] dp = new int[prices.length][2 * k + 1];for (int i = 1; i <= k; i++) {dp[0][2 * i - 1] = -prices[0];}for (int i = 1; i < prices.length; i++) {for (int j = 1; j <= k; j++) {dp[i][2 * j - 1] = Math.max(dp[i - 1][2 * j - 1], dp[i - 1][2 * j - 2] - prices[i]);dp[i][2 * j] = Math.max(dp[i - 1][2 * j], dp[i - 1][2 * j - 1] + prices[i]);}}return dp[prices.length - 1][2 * k];}
}
分析:时间复杂度:O(nk),空间复杂度:O(nk)。
309.最佳买卖股票时机含冷冻期
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/
文档讲解:https://programmercarl.com/0309.%E6%9C%80%E4%BD%B3%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E6…
视频讲解:https://www.bilibili.com/video/BV1rP4y1D7ku
思路
- 确定dp数组以及下标的含义:
dp[i][0]
:持有股票;dp[i][1]
:保持卖出股票;dp[i][2]
:当天卖出股票;dp[i][3]
:冷冻期;
- 确定递推公式:
dp[i][0]
:- 前一天持股:
dp[i - ][0]
; - 前一天不持股:前一天保持卖出股票
dp[i - 1][1] - prices[i]
,前一天是冷冻期dp[i - 1][3] - prices[i]
。
- 前一天持股:
dp[i][1]
:- 前一天保持卖出股票:
dp[i - 1][1]
; - 前一天为冷冻期:
dp[i - 1][3]
。
- 前一天保持卖出股票:
dp[i][2]
:前一天一定持有股票dp[i - 1][0] + prices[i]
。dp[i][3]
:前一天一定卖出了股票dp[i - 1][2]
。
- dp数组如何初始化:
dp[0][0] = -prices[0];
。如果当前状态非法,比如dp[0][1]
,可以通过后面状态的需要来给非法状态赋值,本题给非法状态赋值0。 - 确定遍历顺序:从第二天开始正序遍历。
- 打印dp数组,用于debug
代码
class Solution {public int maxProfit(int[] prices) {int[][] dp = new int[prices.length][4];/*0:持有1:保持卖出2:当天卖出3:冷冻期*/dp[0][0] = -prices[0];for (int i = 1; i < prices.length; i++) {dp[i][0] = Math.max(dp[i - 1][0], Math.max(dp[i - 1][1] - prices[i], dp[i - 1][3] - prices[i]));dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][3]);dp[i][2] = dp[i - 1][0] + prices[i];dp[i][3] = dp[i - 1][2];}return Math.max(dp[prices.length - 1][1], Math.max(dp[prices.length - 1][2], dp[prices.length - 1][3]));}
}
分析:时间复杂度:O(n),空间复杂度:O(4n)。
714.买卖股票的最佳时机含手续费
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
文档讲解:https://programmercarl.com/0714.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4…
视频讲解:https://www.bilibili.com/video/BV1z44y1Z7UR
思路
在买卖股票2的基础上,每次卖股票时减去手续费就可以了:dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
。
代码
class Solution {public int maxProfit(int[] prices, int fee) {int[][] dp = new int[prices.length][2]; // 0为持有,1为卖出dp[0][0] = -prices[0];for (int i = 1; i < prices.length; i++) {dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]);dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);}return Math.max(dp[prices.length - 1][1], dp[prices.length - 1][0]);}
}
分析:时间复杂度:O(n),空间复杂度:O(2n)。
股票总结
文档讲解:https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92-%E8%82%A1%E7%A5…
今日复习
数组理论基础
704. 二分查找
27. 移除元素
977.有序数组的平方
209.长度最小的子数组
59.螺旋矩阵II
数组部分总结