188. Best Time to Buy and Sell Stock IV
leetcode hard
Task
Дан массив целых чисел prices, где prices[i] - это цена данной акции в i-й день, и целое число k.
Найдите максимальную прибыль, которую вы можете получить. Вы можете завершить не более чем k транзакций, т.е. вы можете купить не более k раз и продать не более k раз.
Обратите внимание: Вы не можете участвовать в нескольких транзакциях одновременно (т.е., вы должны продать акцию, прежде чем снова купить).
Пример:
Input: k = 2, prices = [2,4,1]
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
C# solution
matched/originalpublic class Solution {
public int MaxProfit(int k, int[] prices) {
int n = prices.Length;
if (n == 0 || k == 0) return 0;
if (k * 2 >= n) {
int res = 0;
for (int i = 1; i < n; i++)
res += Math.Max(0, prices[i] - prices[i - 1]);
return res;
}
var dp = new int[n, k + 1, 2];
for (int i = 0; i < n; i++) {
for (int j = 0; j <= k; j++) {
dp[i, j, 0] = Int32.MinValue / 2;
dp[i, j, 1] = Int32.MinValue / 2;
}
}
dp[0, 0, 0] = 0;
dp[0, 1, 1] = -prices[0];
for (int i = 1; i < n; i++) {
for (int j = 0; j <= k; j++) {
dp[i, j, 0] = Math.Max(dp[i - 1, j, 0], dp[i - 1, j, 1] + prices[i]);
if (j > 0)
dp[i, j, 1] = Math.Max(dp[i - 1, j, 1], dp[i - 1, j - 1, 0] - prices[i]);
}
}
int res = 0;
for (int j = 0; j <= k; j++)
res = Math.Max(res, dp[n - 1, j, 0]);
return res;
}
}C++ solution
auto-draft, review before submit#include <bits/stdc++.h>
using namespace std;
// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
public int MaxProfit(int k, vector<int>& prices) {
int n = prices.size();
if (n == 0 || k == 0) return 0;
if (k * 2 >= n) {
int res = 0;
for (int i = 1; i < n; i++)
res += max(0, prices[i] - prices[i - 1]);
return res;
}
var dp = new int[n, k + 1, 2];
for (int i = 0; i < n; i++) {
for (int j = 0; j <= k; j++) {
dp[i, j, 0] = Int32.MinValue / 2;
dp[i, j, 1] = Int32.MinValue / 2;
}
}
dp[0, 0, 0] = 0;
dp[0, 1, 1] = -prices[0];
for (int i = 1; i < n; i++) {
for (int j = 0; j <= k; j++) {
dp[i, j, 0] = max(dp[i - 1, j, 0], dp[i - 1, j, 1] + prices[i]);
if (j > 0)
dp[i, j, 1] = max(dp[i - 1, j, 1], dp[i - 1, j - 1, 0] - prices[i]);
}
}
int res = 0;
for (int j = 0; j <= k; j++)
res = max(res, dp[n - 1, j, 0]);
return res;
}
}Java solution
matched/originalpublic class Solution {
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (n <= 0 || k <= 0) {
return 0;
}
if (k * 2 >= n) {
int res = 0;
for (int i = 1; i < n; i++) {
res += Math.max(0, prices[i] - prices[i - 1]);
}
return res;
}
int[][][] dp = new int[n][k + 1][2];
for (int i = 0; i < n; i++) {
for (int j = 0; j <= k; j++) {
dp[i][j][0] = -1000000000;
dp[i][j][1] = -1000000000;
}
}
dp[0][0][0] = 0;
dp[0][1][1] = -prices[0];
for (int i = 1; i < n; i++) {
for (int j = 0; j <= k; j++) { dp[i][j][0] = Math.max(
dp[i - 1][j][0],
dp[i - 1][j][1] + prices[i]
);
if (j > 0) {
dp[i][j][1] = Math.max(
dp[i - 1][j][1],
dp[i - 1][j - 1][0] - prices[i]
);
}
}
}
int res = 0;
for (int j = 0; j <= k; j++) {
res = Math.max(res, dp[n - 1][j][0]);
}
return res;
}
}JavaScript solution
matched/originalclass Solution {
maxProfit(k, prices) {
const n = prices.length;
if (n === 0 || k === 0) return 0;
if (k * 2 >= n) {
let res = 0;
for (let i = 1; i < n; i++) {
res += Math.max(0, prices[i] - prices[i - 1]);
}
return res;
}
const dp = Array.from({ length: n }, () =>
Array.from({ length: k + 1 }, () => Array(2).fill(Number.MIN_SAFE_INTEGER / 2))
);
dp[0][0][0] = 0;
dp[0][1][1] = -prices[0];
for (let i = 1; i < n; i++) {
for (let j = 0; j <= k; j++) {
dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]);
if (j > 0) {
dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]);
}
}
}
return Math.max(...dp[n - 1].map(x => x[0]));
}
}Python solution
matched/originalclass Solution:
def maxProfit(self, k: int, prices: List[int]) -> int:
n = len(prices) if not prices or k == 0:
return 0
if k * 2 >= n:
res = 0
for i, j in zip(prices[1:], prices[:-1]):
res += max(0, i - j)
return res][ishold] = balance
dp = [[[-math.inf] * 2 for _ in range(k + 1)] for _ in range(n)]
dp[0][0][0] = 0
dp[0][1][1] = -prices[0]
for i in range(1, n):
for j in range(k + 1):
dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i]
if j > 0:
dp[i][j][1] = max(
dp[i - 1][j][1], dp[i - 1][j - 1][0] - prices[i]
)
res = max(dp[n - 1][j][0] for j in range(k + 1))
return resGo solution
matched/originaltype Solution struct{}
func maxProfit(k int, prices []int) int {
n := len(prices)
if n == 0 || k == 0 {
return 0
}
if k*2 >= n {
res := 0
for i := 1; i < n; i++ {
if prices[i] > prices[i-1] {
res += prices[i] - prices[i-1]
}
}
return res
}
dp := make([][][]int, n)
for i := range dp {
dp[i] = make([][]int, k+1)
for j := range dp[i] {
dp[i][j] = make([]int, 2)
dp[i][j][0], dp[i][j][1] = -1<<31/2, -1<<31/2
}
}
dp[0][0][0] = 0
dp[0][1][1] = -prices[0]
for i := 1; i < n; i++ {
for j := 0; j <= k; j++ {
dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1]+prices[i])
if j > 0 {
dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i])
}
}
}
res := 0
for j := 0; j <= k; j++ {
res = max(res, dp[n-1][j][0])
}
return res
}
func max(x, y int) int {
if x > y {
return x
}
return y
}Explanation
Algorithm
1️⃣
Инициализация DP массива: Инициализируйте трехмерный массив dp, где dp[i][j][l] представляет максимальную прибыль на конец i-го дня с j оставшимися транзакциями и l акциями в портфеле. Начните с dp[0][0][0] = 0 (нет прибыли без акций и транзакций) и dp[0][1][1] = -prices[0] (покупка первой акции).
2️⃣
Вычисление переходов: Для каждого дня и каждого возможного количества транзакций вычислите возможные действия: держать акцию, не держать акцию, купить акцию, если j > 0, или продать акцию. Обновляйте dp с использованием:
dp[i][j][1] = max(dp[i−1][j][1], dp[i−1][j−1][0] - prices[i]) (максимум между удержанием акции и покупкой новой).
dp[i][j][0] = max(dp[i−1][j][0], dp[i−1][j][1] + prices[i]) (максимум между неудержанием акции и продажей).
3️⃣
Расчет результатов: По завершении всех дней, возвращайте максимальное значение dp[n-1][j][0] для всех j от 0 до k, что представляет максимальную прибыль без удержания акций на последний день. Обработайте специальный случай, когда 𝑘×2≥𝑛, чтобы избежать лишних расчетов.
😎