在问 · 算法题解

188. 买卖股票的最佳时机 IV

题目描述

输入整数 k 和数组 prices,prices[i] 是某只股票第 i 天的价格。

一笔交易指先买入一次、之后再卖出一次。你最多完成 k 笔交易。手里最多持有一股:再次买入前,必须先卖掉手上的股票。

返回能获得的最大利润。

示例 1
输入:k = 2, prices = [2,4,1]
输出:2

解释:第 1 天以 2 买入,第 2 天以 4 卖出,赚 2。

示例 2
输入:k = 2, prices = [3,2,6,5,0,3]
输出:7

解释:第 2 天以 2 买、第 3 天以 6 卖赚 4;第 5 天以 0 买、第 6 天以 3 卖赚 3,共 7。

数据范围

  • 1 <= k <= 100
  • 1 <= prices.length <= 1000
  • 0 <= prices[i] <= 1000

解题思路

每天结束时,按“已经发起了几笔交易、手里有没有股票”划分状态。buy[j] 表示已进行第 j 次买入且持股时的最大余额,sell[j] 表示已完成 j 笔交易、空仓时的最大余额。今天的 buy[j] 要么保持,要么由 sell[j-1] 花 p 买入;sell[j] 要么保持,要么把 buy[j] 以 p 卖出。按天滚动更新即可。

为什么正确

处理完第 t 天后,buy[j] 和 sell[j] 是前 t 天里对应状态能达到的最大余额。

复杂度分析

时间 O(nk),空间 O(k)。

易错点

buy 的初值不能是 0,否则相当于“免费持股”;另外第 j 次买入只能接在 sell[j-1] 后面,不能接在 sell[j] 后面。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        buy = [-math.inf] * (k + 1)
        sell = [0] * (k + 1)
        for p in prices:
            for j in range(1, k + 1):
                buy[j] = max(buy[j], sell[j - 1] - p)
                sell[j] = max(sell[j], buy[j] + p)
        return sell[k]

载入编辑器,自己跑一遍 →

动态规划 专题的其他题目

查看 动态规划 全部题目 →