Go 刷 leetcode|割冷冻韭菜的最佳时机

共 1165字,需浏览 3分钟

 ·

2020-07-29 05:20

今天为大家讲解 LeetCode 第 309 题,是昨天带来的 《Go leetcode|割韭菜的最佳时机 的一个升级版,不了解的朋友建议先去看看。

题目描述

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。示例:

输入: [1,2,3,0,2] 输出: 3 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

动态规划

了解的朋友可能知道「买股票」有一系列的题目,可以的话我会一一讲解。

这一系列的题也正涉及了重要的「动态规划」

这里先区别一下「买股票」系列中这道题的不同:

这道题增加了「冷冻期」这样一个条件,没有限制多少笔交易。因此只需要增加一个状态。

第一步:状态定义

dp[i][j] 表示[0, i]区间内,在下标为i这一天状态为j时的最大收益。

这里j取三个值:

  • 0 表示不持股;
  • 1 表示持股;
  • 2 表示处在冷冻期。

第二部:状态转移方程

这步是至关重要也是最难的,得知状态转移方程的关键是理解题意,理清逻辑。

  • 不持股可以由这两个状态转换而来:昨天不持股,今天什么都不操作,仍然不持股;昨天持股,今天卖了一股。
  • 持股可以由这两个状态转换而来:昨天持股,今天什么都不操作,仍然持股;昨天处在冷冻期,今天买了一股;
  • 处在冷冻期比较特殊,只可以由不持股转换而来,因为题目中说,刚刚把股票卖了,需要冷冻 1 天。(持股卖了变成不持股,再变成冷冻期)

以上分析可以用下图表示:

第三步:初始化(base case)

在第 0 天,不持股的初始化值为 0

持股的初始化值为 -prices[0](表示购买了一股),

虽然不处于冷冻期,但是初始化的值可以为 0

第四步:返回值

每一天都由前面几天的状态转换而来,最优值在最后一天。取不持股和冷冻期的最大者。

代码实现

//go
func maxProfit(prices []int) int {
 length := len(prices)
 // 特殊判断
 if length <= 1 {
  return 0
 }
 // 声明dp
 dp := make([][3]int, length)
 // 初始化
 dp[0][0] = 0          // 【0天】【不持股】
 dp[0][1] = -prices[0// 【0天】【持股】
 dp[0][2] = 0          // 【0天】【冷冻期】

 for i := 1; i < length; i++ {
  // 【第i天】【不持股】 = max(昨天不持股今天不操作,昨天持股+今天卖一股)
  dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
  // 【第i天】【持股】 = max(昨天持股今天不操作,昨天冷冻期+今天买一股)
  dp[i][1] = max(dp[i-1][1], dp[i-1][2]-prices[i])
  // 【第i天】【冷冻期】 = 昨天卖了不持股
  dp[i][2] = dp[i-1][0]
 }

 // 返回不持股和冷冻期的最大者
 return max(dp[length-1][0], dp[length-1][0])
}

func max(x, y int) int {
 if x > y {
  return x
 }
 return y
}
//java
public class Solution {

    public int maxProfit(int[] prices) {
        int len = prices.length;
        // 特判
        if (len < 2) {
            return 0;
        }

        int[][] dp = new int[len][3];

        // 初始化
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        dp[0][2] = 0;

        for (int i = 1; i < len; 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][2] - prices[i]);
            dp[i][2] = dp[i - 1][0];
        }
        return Math.max(dp[len - 1][0], dp[len - 1][2]);
    }
}

郑重声明:

所展示代码已通过 LeetCode 运行通过,请放心食用~



推荐阅读



学习交流 Go 语言,扫码回复「进群」即可


站长 polarisxu

自己的原创文章

不限于 Go 技术

职场和创业经验


Go语言中文网

每天为你

分享 Go 知识

Go爱好者值得关注


浏览 49
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报