描述

给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。

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

思路

可以使用动态规划求解该题。

首先可以将每天的交易状态分为下述情况:

  • 没有过任何交易
  • 进行过第1次买入
  • 进行过第1次卖出
  • 进行过第2次买入
  • 进行过第2次卖出
  • ……
  • 进行过第n次买入
  • 进行过第n次卖出 共有 $2k+1$ 个状态。

而每个状态之间存在下述转移关系:

\[本日进行过第i次买入的总利润=max\left( \begin{aligned} 昨日进行过第[i-1]次卖出的总利润 - 本日股价 \\ 昨日进行过第i次买入的总利润 \\ \end{aligned} \right)\] \[本日进行过第i次卖出的总利润=max\left( \begin{aligned} 昨日进行过第i次买入的总利润 + 本日股价 \\ 昨日进行过第i次卖出的总利润 \\ \end{aligned} \right)\]

通过动态规划按照上述状态与状态转移进行求解即可,最终获得的最大利润即为最后一天所有状态中的最大值。

上述方法同样适用于买卖股票的最佳时机III

代码

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        vector<vector<int>> dp;

        for (const auto& price: prices) {
            dp.emplace_back(vector<int>(k * 2 + 1));
        }

        dp[0][0] = 0;
        for (size_t idx = 1; idx <= 2 * k; idx += 2) {
            dp[0][idx] = -prices[0];
            dp[0][idx + 1] = 0;
        }

        for (size_t day = 1; day < prices.size(); day++) {
            dp[day][0] = dp[day - 1][0];

            for (size_t idx = 1; idx <= 2 * k; idx += 2) {
                dp[day][idx] = max(dp[day - 1][idx - 1] - prices[day], dp[day - 1][idx]);
                dp[day][idx + 1] = max(dp[day - 1][idx] + prices[day], dp[day - 1][idx + 1]);
            }
        }

        return *max_element(dp.back().begin(), dp.back().end());
    }
};

留下评论