leetcode : 123. 买卖股票的最佳时机 III

123. 买卖股票的最佳时机 III


前言

链接: 题目连接与题解.


一、题目?

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例1

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,
     这笔交易所能获得利润 = 3-0 = 3 。
     随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,
     这笔交易所能获得利润 = 4-1 = 3 。

示例2

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出,
     这笔交易所能获得利润 = 5-1 = 4 。   
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。   
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例3

输入:prices = [7,6,4,3,1] 
输出:0 
解释:在这个情况下, 没有交易完成, 所以最大利润为 0。

二、思路与算法

1.动态规划

由于我们最多可以完成两笔交易,因此在任意一天结束之后,我们会处于以下五个状态中的一种:

  • 未进行过任何操作;

  • buy1-----只进行过一次买操作;

  • sell1-----进行了一次买操作和一次卖操作,即完成了一笔交易;

  • buy2-----在完成了一笔交易的前提下,进行了第二次买操作;

  • sell2-----完成了全部两笔交易。

未进行任何操作的利润为0,不必记录。剩下四个,分别将最大利润记为buy1,sell1,buy2,sell2

那么,知道了第i-1天结束后的四个状态,如何通过状态转移方程得到第 ii 天结束后的这四个状态呢?

buy1:

  1. i天不进行任何操作,保持不变。

  2. 在未进行任何操作的前提下以 prices[i] 的价格买入股票。

    buy1的状态转移方程: b u y 1 = m a x { b u y 1 ′ , − p r i c e s [ i ] } buy_1= max\left\{buy^{'}_{1}, - prices[i]\right\} buy1=max{buy1,prices[i]}

    buy1是第i-1天的状态, 与第i的天buy1做区分

sell1:

  1. i天不进行任何操作,保持不变。

  2. 只进行过一次买操作的前提下以 prices[i] 的价格卖出股票。

    sell1的状态转移: s e l l 1 = m a x { s e l l 1 ′ , b u y 1 ′ + p r i c e s [ i ] } sell_1= max\left\{sell^{'}_{1}, buy^{'}_{1}+ prices[i]\right\} sell1=max{sell1,buy1+prices[i]}

同理

buy2状态转移方程: b u y 2 = m a x { b u y 2 ′ , s e l l 1 ′ − p r i c e s [ i ] } buy_2= max\left\{buy^{'}_{2}, sell^{'}_{1}- prices[i]\right\} buy2=max{buy2,sell1prices[i]}

sell2状态转移方程: s e l l 2 = m a x { s e l l 2 ′ , b u y 2 ′ + p r i c e s [ i ] } sell_2= max\left\{sell^{'}_{2}, buy^{'}_{2}+ prices[i]\right\} sell2=max{sell2,buy2+prices[i]}

注意,在考虑边界条件,存在事实

在同一天买入并且卖出, 不影响当天利润,没有收益

所有,状态转移可以写成:
{ b u y 1 = m a x { b u y 1 , − p r i c e s [ i ] } , s e l l 1 = m a x { s e l l 1 , b u y 1 + p r i c e s [ i ] } , b u y 2 = m a x { b u y 2 , s e l l 1 − p r i c e s [ i ] } , s e l l 2 = m a x { s e l l 2 , b u y 2 + p r i c e s [ i ] } . \left\{ \begin{aligned} buy_1= max\left\{buy_{1}, - prices[i]\right\}, \\ sell_1= max\left\{sell_{1}, buy_{1}+ prices[i]\right\}, \\ buy_2= max\left\{buy_{2}, sell_{1}- prices[i]\right\}, \\ sell_2= max\left\{sell_{2}, buy_{2}+ prices[i]\right\}. \\ \end{aligned} \right. buy1=max{buy1,prices[i]},sell1=max{sell1,buy1+prices[i]},buy2=max{buy2,sell1prices[i]},sell2=max{sell2,buy2+prices[i]}.
这里详细解释为什么在上面去除了上标:

  1. 对于买操作,buy1, buy2: 对前一天不进行操作buy1 = buy1, buy2 = buy2

  2. 对于卖操作,sell1, sell2: 对前一天不进行操作, 相当于在第i天买入又卖出,sell1 = sell1 - prices[i] + prices[i] = sell1

那么边界的起始条件,在第i天,

  • buy1 = -prices[0]

  • sell1 = buy1 = -prices[0] = 0

  • buy2 = -prices[0]

  • sell2 = buy2 = -prices[0] = 0

i=1开始进行动态规划,由题求出进行不超过两笔交易的最大值,则最终答案在0,sell1,sell2的最大值。

边界条件中,sell1=sell2, 且维护最大值,故sell1=sell2 > 0。 且若进行一次就可以获得最大值,可放宽看做最后一天买入又卖出进行了两次交易,故最终返回sell2

2.代码题解

代码如下(示例):

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)
        buy1 = buy2 = -prices[0]
        sell1 = sell2 = 0
        for i in range(1, n):
            buy1 = max(buy1, -prices[i])
            sell1 = max(sell1, buy1 + prices[i])
            buy2 = max(buy2, sell1 - prices[i])
            sell2 = max(sell2, buy2 + prices[i])
        return sell2
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值