123. Best Time to Buy and Sell Stock III

遍历 prices,对于每个元素(价格)都有三个选择:1.买,2.卖,3.不操作,终止条件也很明确:遍历结束,或买/卖均达到2次。

Backtracking

树形发展的多个sequence里面找合格/最优,我觉得可以试试 backtracking,但这题直接这样写会 TLE,即便已经用了memo.

DP - max future profit

改成 DP 返回当前位置往后可能的 max profit,相当于从终止(0)往前逆增,勉强能过。

Max Rise

基于 121. Best Time to Buy and Sell Stock 解法,在 prices 序列里寻找两个最大增幅区间。

直接在整个prices里面找 max rise 结果是(a, b),两个最大增幅区间就会有三种情况:

  1. 第二个 max rise 在 day a 之前,即 y <= a,那在 prices[:a] 里找一次即可;

  2. 第二个 max rise 在 day b 之后,即 x >= b,那在 prices[b:] 里找一次即可;

  3. 两个 max rise 分别是 (a, x) 和 (y, b),即 day x 做了第一次卖出之后,等到价格下降到 day y 又做了第二次买入,那相当于要在 (a, b) 之间找 max drop,实际上就是在prices[b:a]里找 max rise;

DP - State Machine

整个过程里,除了初始状态(没做任何买入)之外,只有四个状态:

  1. 第一次 holding stock

  2. 第一次 sold stock

  3. 第二次 holding stock

  4. 第二次 sold stock

设置四个变量来代表四个状态的 max profit,遍历 prices 来更新四个变量。

Easy DP solution using state machine, O(n) time complexity, O(1) space complexity

DP - max previous profit

这个实际上是 188. Best Time to Buy and Sell Stock IV 的 DP 解法,对于每一天的最高 balance,有两个可能的计算方式:

  1. 不做任何交易 -> 那就等于前一天的 balance;

  2. 卖出股票 -> 那就等于今天的价格减去之前某天 day m 的价格,再加上在 day m 之前做 K-1 笔交易可能的最高 balance;

f[i][j] = max(f[i][j-1], max(prices[j] - prices[m] + f[i-1][m] for m in range(0, j-1)]
188. Best Time to Buy and Sell Stock IV
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        
        def maxRise(left, right, step):
            prevLow, diff = left, 0
            low, high = 0, 0
            for i in range(left, right, step):
                if prices[i] < prices[prevLow]:
                    prevLow = i
                if prices[i] - prices[prevLow] > diff:
                    diff = prices[i] - prices[prevLow]
                    low, high = prevLow, i
            return (low, high, diff)
        
        
        n = len(prices)
        low, high, rise = maxRise(0, n, 1)
        a, b, c = maxRise(0, low, 1)[2], maxRise(high+1, n, 1)[2], maxRise(high-1, low, -1)[2]
        return rise + max([a, b, c])
            

Last updated

Was this helpful?