一个函数解决【LeetCode 买卖股票的最佳时机】系列所有题目!

题目和题解汇总

之前介绍了【LeetCode 买卖股票的最佳时机】系列一共六道题目,这里把之前的题解还有题目链接汇总一下,方便大家查找。

第一题

LeetCode 121. 买卖股票的最佳时机[1]

每日算法系列【LeetCode 121】买卖股票的最佳时机

第二题

LeetCode 122. 买卖股票的最佳时机 II[2]

每日算法系列【LeetCode 122】买卖股票的最佳时机 II

第三题

LeetCode 123. 买卖股票的最佳时机 III[3]

每日算法系列【LeetCode 123】买卖股票的最佳时机 III

第四题

LeetCode 188. 买卖股票的最佳时机 IV[4]

每日算法系列【LeetCode 188】买卖股票的最佳时机 IV

第五题

LeetCode 714. 买卖股票的最佳时机含手续费[5]

每日算法系列【LeetCode 714】买卖股票的最佳时机含手续费

第六题

LeetCode 309. 最佳买卖股票时机含冷冻期[6]

每日算法系列【LeetCode 309】最佳买卖股票时机含冷冻期

通用解法

上面六道题目中,前四题限制了买卖的次数,第五题加入了手续费,第六题加入了冻结时间。所以我们提出一般性的问题:

给定每天的价格  ,最大买卖次数  ,手续费  ,冻结时间  ,求最大利润。

观察前面六题的代码,我们可以在第四题基础上进行修改,这样代码量比较小。

首先是增加手续费,这个很简单,只需要在  更新时减去一个手续费  就行了。

有点麻烦的是冻结时间。在第六题代码中,增加了一个维度用来保存每一只股票之前(包含)的最大利润,目的是为了获取相隔一个冻结时间之前的股票以前可以获得的最大利润。但是通用情况下不能这么保存,不然的话空间复杂度就变成了  ,极限情况下会爆掉。

解决方法就是,因为对于第  只股票来说,只需要访问它与  之间的数值,那么我们只需要保存  大小的数组就行了。在访问的时候,采用取模的方法,来让数组滚动起来。

还有一些细节,比如如果  ,那么问题就退化为了没有买卖次数限制,也就是第五题和第六题的情况。如果不这样处理的话,按照上面方法做,时间复杂度和空间复杂度都是  ,可能会吃不消。

代码

通用函数

class Solution:
    def solve(self, prices, k=1, fee=0, freeze=0):
        n = len(prices)
        if n == 0 or k == 0: return 0
        limit = 0 if k >= n//2 else 1
        k = 1 if k >= n//2 else k
        dp0 = [-prices[0]] * (k+1)
        dp1 = [[0]*(k+1) for _ in range(freeze+1)]
        for i in range(1, n):
            for j in range(1, k+1):
                dp0[j] = max(dp0[j], dp1[i%(freeze+1)][j-1 if limit else j]-prices[i])
                dp1[i%(freeze+1)][j] = max(dp1[(i-1)%(freeze+1)][j], dp0[j]+prices[i]-fee)
        return max(dp1[(n-1)%(freeze+1)][k], 0)

第一题

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        return self.solve(prices, k=1, fee=0, freeze=0)

第二题

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        return self.solve(prices, k=len(prices), fee=0, freeze=0)

第三题

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        return self.solve(prices, k=2, fee=0, freeze=0)

第四题

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        return self.solve(prices, k, fee=0, freeze=0)

第五题

class Solution:
    def maxProfit(self, prices: List[int], fee: int) -> int:
        return self.solve(prices, len(prices), fee, 0)

第六题

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        return self.solve(prices, k=len(prices), fee=0, freeze=1)

参考资料

[1]

LeetCode 121. 买卖股票的最佳时机: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/

[2]

LeetCode 122. 买卖股票的最佳时机 II: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/

[3]

LeetCode 123. 买卖股票的最佳时机 III: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/

[4]

LeetCode 188. 买卖股票的最佳时机 IV: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/

[5]

LeetCode 714. 买卖股票的最佳时机含手续费: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/

[6]

LeetCode 309. 买卖股票的最佳时机: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/

1、【算法提高班】《贪婪策略》系列 - 覆盖篇

2、【LeetCode日记】 335. 路径交叉

3、一行代码就可以通过 LeetCode?来看下我是怎么做到的!

4、原来状态机也可以用来刷LeetCode?

5、【算法提高班】《我的日程安排表》系列

6、【算法提高班】并查集

如果觉得文章不错,帮忙点个在看呗

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值