309. 最佳买卖股票时机含冷冻期
链接
文章链接
题目链接
第一想法
之前做过买卖股票的最佳时机I、II、III、IV,所以这道题只是添加了一个冷冻期,昨天卖了今天不能买,只能第二天再买,所以就是把递推公式改一下就可以了,接下来递归五部曲:
- dp数组的含义,还是和I是一样的,dp[i][0]是持有股票时现金的最大值,dp[i][1]是不持有股票时现金的最大值
- 递推公式:dp[i][1]还是一样的,有两种情况,第i-1天就是不持有和第i-1天持有而第i天卖出,所以递推公式为
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i])
;唯一不同的就是dp[i][0]了,也是有两种情况,第一种是第i-1天就持有,第二种是i-1天不持有,第i天想买,如果想买的话,因为有冷冻期,所以最起码在i-2天就不持有股票时第i天才能买,所以递推公式为dp[i][0] = Math.max(dp[i - 1][0], (dp[i - 2]?.[1] || 0) - prices[i])
这里的?.是js的语法,前面为undefined时就返回0 - 初始化,还是一样的
dp[0] = [-prices[0], 0]
- 遍历顺序也是一样的
代码如下:
function maxProfit(prices: number[]): number {
let dp: number[][] = new Array(prices.length).fill(0).map((item) => new Array())
dp[0] = [-prices[0], 0]
for (let i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], (dp[i - 2]?.[1] || 0) - prices[i])
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i])
}
return dp[prices.length - 1][1]
}
看完文章后的想法
文章的想法是和我的完全不一样的,但是我感觉我的思路也是正确的,文章也是用的二维数组,但是它的dp[i]有四个状态,分别为dp[i][0]:持股状态,dp[i][1]:不持股但是也不是冷冻期,dp[i][2]:不持股但是是今天卖出,dp[i][3]:不持股今天是冷冻期。那么直接递归五部曲:
- dp数组的含义,上面已经说了,所以这里不再多说了、
- 递推公式,首先是dp[i][0],共有三种情况,第i-1天就是持有状态,第二种是当前购买且前一天是不持股状态也不是冷冻期,第三种情况是当天购买且前一天是冷冻期;dp[i][1]有两种状态,第一种是i-1天是不持股状态也不是冷冻期,第二种是i-1天是冷冻期;dp[i][2],当前卖出只有状态,只有i-1天是持有状态,dp[i][3]也只有一种状态,i-1天是卖出股票的状态
- 初始化,很容易理解,除了持有股票,其他都是0
- 遍历顺序还是一样的
function maxProfit(prices: number[]): number {
let dp: number[][] = new Array(prices.length).fill(0).map((item) => new Array())
dp[0] = [-prices[0], 0, 0, 0]
for (let i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], 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], dp[prices.length - 1][2], dp[prices.length - 1][3])
}
思考
这道题不是很难,但是我和文章的思路是不太相同的,文章把状态分的很细,但是由于是自己想的,还是认为自己的比较好理解。
714. 买卖股票的最佳时机含手续费
链接
题目链接
文章链接
第一想法
之前是拿贪心算法写的,不太好理解,这次拿动态规划写,由于之前写了很多的买卖股票的题,所以这回非常就想到了,只要在卖股票的时候再减一个手续费就可以了,递归五部曲
- dp数组的含义,dp[i][0]是持有股票时的最大现金数,dp[i][1]是不持有股票时的最大现金数
- 递推公式,dp[i][0]还是不变的,有两种情况,前一天就持有或者是前一天不持有今天购买
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i])
dp[i][1]也是两种情况,前一天就不持有或者是前一天持有今天选择卖出,那么卖出则需要支付手续费dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee)
- 初始化,还是dp[0]=[-prices[i],0]
- 遍历顺序还是从前往后的
function maxProfit(prices: number[], fee: number): number {
let dp: number[][] = new Array(prices.length).fill(0).map((item) => new Array())
dp[0] = [-prices[0], 0]
for (let 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 dp[prices.length - 1][1]
}
看完文章后的想法
文章的想法和我的想法是一样的,所以这里就不多赘述了
思考
这道题不算太难,只要把卖股票的时候添加上手续费就可以了
今日总结
今天都不算太难,主要是利用买卖股票的模版加上变一下递推公式就可以了,所以没费很长时间,今日耗时2小时