给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入:k = 2, prices = [2,4,1] 输出:2 解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例 2:
输入:k = 2, prices = [3,2,6,5,0,3]
输出:7
解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
提示:
1 <= k <= 1001 <= prices.length <= 10000 <= prices[i] <= 1000
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
vector<vector<int>> dp(k + 1, vector<int>(n, 0));
for (int t = 1; t <= k; ++t) {
int max_diff = -prices[0]; // 初始化最大差值
for (int i = 1; i < n; ++i) {
dp[t][i] = max(dp[t][i - 1], prices[i] + max_diff);
max_diff = max(max_diff, dp[t - 1][i] - prices[i]);
}
}
return dp[k][n - 1]; // 返回最多 k 笔交易的最大利润
}
};
vector<vector<int>> dp(k + 1, vector<int>(n, 0));k + 1 是该数组的第一维大小,表示从 0 次交易到最多 k 次交易,因此共有 k + 1 行。
dp[t][i] 表示最多进行 t 笔交易并且在第 i 天结束时能获取的最大利润
对于每一笔交易 t,我们遍历每一天 i,尝试计算出在第 i 天最多进行 t 次交易的最大利润。
dp[t][i] = max(dp[t][i-1], prices[i] + max_diff):dp[t][i-1]表示在不进行交易的情况下,最大利润为前一天的利润。prices[i] + max_diff表示在第i天卖出股票所获得的最大利润。
max_diff = max(max_diff, dp[t-1][i] - prices[i]):dp[t-1][i] - prices[i]表示在第i天之前最多进行t-1笔交易的最大利润,减去第i天买入股票的价格。这帮助我们在后续天数计算中寻找最佳的买入点。
假设:prices = [3, 2, 6, 5, 0, 3],k = 2
第 1 笔交易时 (t = 1):
初始化 max_diff = -prices[0] = -3,表示第 0 天买入的代价。
-
第 1 天 (
i = 1):dp[1][1] = max(dp[1][0], prices[1] + max_diff)dp[1][1] = max(0, 2 + (-3)) = 0- 更新
max_diff:max_diff = max(-3, dp[0][1] - prices[1]) = max(-3, 0 - 2) = -2
-
第 2 天 (
i = 2):dp[1][2] = max(dp[1][1], prices[2] + max_diff)dp[1][2] = max(0, 6 + (-2)) = 4(第 1 天买入,第 2 天卖出)- 更新
max_diff:max_diff = max(-2, dp[0][2] - prices[2]) = max(-2, 0 - 6) = -2(保持不变)
-
第 3 天 (
i = 3):dp[1][3] = max(dp[1][2], prices[3] + max_diff)dp[1][3] = max(4, 5 + (-2)) = 4(不交易,维持第 2 天的利润)- 更新
max_diff:max_diff = max(-2, dp[0][3] - prices[3]) = max(-2, 0 - 5) = -2
-
第 4 天 (
i = 4):dp[1][4] = max(dp[1][3], prices[4] + max_diff)dp[1][4] = max(4, 0 + (-2)) = 4- 更新
max_diff:max_diff = max(-2, dp[0][4] - prices[4]) = max(-2, 0 - 0) = 0
-
第 5 天 (
i = 5):dp[1][5] = max(dp[1][4], prices[5] + max_diff)dp[1][5] = max(4, 3 + 0) = 4- 更新
max_diff:max_diff = max(0, dp[0][5] - prices[5]) = max(0, 0 - 3) = 0
第一笔交易完成,dp[1][n-1] = dp[1][5] = 4,意味着在最多进行 1 笔交易的情况下,最大利润是 4。
第 2 笔交易时 (t = 2):
初始化 max_diff = -prices[0] = -3。
-
第 1 天 (
i = 1):dp[2][1] = max(dp[2][0], prices[1] + max_diff)dp[2][1] = max(0, 2 + (-3)) = 0- 更新
max_diff:max_diff = max(-3, dp[1][1] - prices[1]) = max(-3, 0 - 2) = -2
-
第 2 天 (
i = 2):dp[2][2] = max(dp[2][1], prices[2] + max_diff)dp[2][2] = max(0, 6 + (-2)) = 4- 更新
max_diff:max_diff = max(-2, dp[1][2] - prices[2]) = max(-2, 4 - 6) = -2
-
第 3 天 (
i = 3):dp[2][3] = max(dp[2][2], prices[3] + max_diff)dp[2][3] = max(4, 5 + (-2)) = 4- 更新
max_diff:max_diff = max(-2, dp[1][3] - prices[3]) = max(-2, 4 - 5) = -1
-
第 4 天 (
i = 4):dp[2][4] = max(dp[2][3], prices[4] + max_diff)dp[2][4] = max(4, 0 + (-1)) = 4- 更新
max_diff:max_diff = max(-1, dp[1][4] - prices[4]) = max(-1, 4 - 0) = 4
-
第 5 天 (
i = 5):dp[2][5] = max(dp[2][4], prices[5] + max_diff)dp[2][5] = max(4, 3 + 4) = 7- 更新
max_diff:max_diff = max(4, dp[1][5] - prices[5]) = max(4, 4 - 3) = 4
第二笔交易完成,dp[2][n-1] = dp[2][5] = 7,意味着在最多进行 2 笔交易的情况下,最大利润是 7。
方法二:
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
vector<int> buy(k + 1, INT_MIN);
vector<int> sell(k + 1, 0);
for (int price : prices) {
for (int j = 1; j <= k; ++j) {
buy[j] = max(buy[j], sell[j - 1] - price); // 买入操作
sell[j] = max(sell[j], buy[j] + price); // 卖出操作
}
}
return sell[k]; // 最终返回最大利润
}
};
vector<int> buy(k + 1, INT_MIN);
初始状态下的利润设置为极小值。这是因为在一开始我们还没有进行任何买入操作,初始状态下假设买入的利润极低(也就是不可能)。
buy[j]:表示最多进行j笔交易后,当前手上持有股票时的最大利润sell[j]:表示最多进行j笔交易后,当前手上不持有股票时的最大利润
155

被折叠的 条评论
为什么被折叠?



