From 89bb0bda721117079f52d9aba942d49b109b9480 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Sun, 8 Jun 2025 20:43:40 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3573 No.3573.Best Time to Buy and Sell Stock V --- .../README.md | 149 +++++++++++++++++- .../README_EN.md | 149 +++++++++++++++++- .../Solution.cpp | 22 +++ .../Solution.go | 22 +++ .../Solution.java | 19 +++ .../Solution.py | 17 ++ .../Solution.ts | 25 +++ 7 files changed, 395 insertions(+), 8 deletions(-) create mode 100644 solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.cpp create mode 100644 solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.go create mode 100644 solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.java create mode 100644 solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.py create mode 100644 solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.ts diff --git a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README.md b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README.md index bac69af463f82..626bdf7cfc802 100644 --- a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README.md +++ b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README.md @@ -82,32 +82,173 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3573.Be -### 方法一 +### 方法一:动态规划 + +我们定义 $f[i][j][k]$ 表示在前 $i$ 天内,最多进行 $j$ 笔交易,且当前状态为 $k$ 时的最大利润。这里的状态 $k$ 有三种可能: + +- 若 $k = 0$,表示当前没有持有股票。 +- 若 $k = 1$,表示当前持有一支股票。 +- 若 $k = 2$,表示当前持有一支股票的空头。 + +初始时,对任意 $j \in [1, k]$,都有 $f[0][j][1] = -prices[0]$ 和 $f[0][j][2] = prices[0]$。这表示在第 0 天买入一支股票或卖出一支股票的空头。 + +接下来,我们可以通过状态转移来更新 $f[i][j][k]$ 的值。对于每一天 $i$ 和每笔交易 $j$,我们可以根据当前状态 $k$ 来决定如何更新: + +- 若 $k = 0$,表示当前没有持有股票,这个状态可以由以下三种情况转移而来: + - 前一天没有持有股票。 + - 前一天持有一支股票,并在今天卖出。 + - 前一天持有一支股票的空头,并在今天买回。 +- 若 $k = 1$,表示当前持有一支股票,这个状态可以由以下两种情况转移而来: + - 前一天持有一支股票。 + - 前一天没有持有股票,并在今天买入。 +- 若 $k = 2$,表示当前持有一支股票的空头,这个状态可以由以下两种情况转移而来: + - 前一天持有一支股票的空头。 + - 前一天没有持有股票,并在今天卖出。 + +即,对于 $1 \leq i < n$ 和 $1 \leq j \leq k$,我们有以下状态转移方程: + +$$ +\begin{aligned} +f[i][j][0] &= \max(f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]) \\ +f[i][j][1] &= \max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]) \\ +f[i][j][2] &= \max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]) +\end{aligned} +$$ + +最终,我们需要返回 $f[n - 1][k][0]$,即在前 $n$ 天内,最多进行 $k$ 笔交易,且当前没有持有股票时的最大利润。 + +时间复杂度 $O(n \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 为数组 $\textit{prices}$ 的长度,而 $k$ 为最大交易次数。 #### Python3 ```python - +class Solution: + def maximumProfit(self, prices: List[int], k: int) -> int: + n = len(prices) + f = [[[0] * 3 for _ in range(k + 1)] for _ in range(n)] + for j in range(1, k + 1): + f[0][j][1] = -prices[0] + f[0][j][2] = prices[0] + for i in range(1, n): + for j in range(1, k + 1): + f[i][j][0] = max( + f[i - 1][j][0], + f[i - 1][j][1] + prices[i], + f[i - 1][j][2] - prices[i], + ) + f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]) + f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]) + return f[n - 1][k][0] ``` #### Java ```java - +class Solution { + public long maximumProfit(int[] prices, int k) { + int n = prices.length; + long[][][] f = new long[n][k + 1][3]; + for (int j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + for (int i = 1; i < n; ++i) { + for (int j = 1; j <= k; ++j) { + f[i][j][0] = Math.max(f[i - 1][j][0], + Math.max(f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i])); + f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + return f[n - 1][k][0]; + } +} ``` #### C++ ```cpp - +class Solution { +public: + long long maximumProfit(vector& prices, int k) { + int n = prices.size(); + long long f[n][k + 1][3]; + memset(f, 0, sizeof(f)); + for (int j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + + for (int i = 1; i < n; ++i) { + for (int j = 1; j <= k; ++j) { + f[i][j][0] = max({f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]}); + f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + + return f[n - 1][k][0]; + } +}; ``` #### Go ```go +func maximumProfit(prices []int, k int) int64 { + n := len(prices) + f := make([][][3]int, n) + for i := range f { + f[i] = make([][3]int, k+1) + } + + for j := 1; j <= k; j++ { + f[0][j][1] = -prices[0] + f[0][j][2] = prices[0] + } + + for i := 1; i < n; i++ { + for j := 1; j <= k; j++ { + f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1]+prices[i], f[i-1][j][2]-prices[i]) + f[i][j][1] = max(f[i-1][j][1], f[i-1][j-1][0]-prices[i]) + f[i][j][2] = max(f[i-1][j][2], f[i-1][j-1][0]+prices[i]) + } + } + + return int64(f[n-1][k][0]) +} +``` +#### TypeScript + +```ts +function maximumProfit(prices: number[], k: number): number { + const n = prices.length; + const f: number[][][] = Array.from({ length: n }, () => + Array.from({ length: k + 1 }, () => Array(3).fill(0)), + ); + + for (let j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + + for (let i = 1; i < n; ++i) { + for (let j = 1; j <= k; ++j) { + f[i][j][0] = Math.max( + f[i - 1][j][0], + f[i - 1][j][1] + prices[i], + f[i - 1][j][2] - prices[i], + ); + f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + + return f[n - 1][k][0]; +} ``` diff --git a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README_EN.md b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README_EN.md index abac1b74b30c1..219c7febe4a1e 100644 --- a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README_EN.md +++ b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README_EN.md @@ -80,32 +80,173 @@ We can make $36 of profit through 3 transactions: -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j][k]$ to represent the maximum profit on the first $i$ days, with at most $j$ transactions, and the current state $k$. Here, the state $k$ has three possibilities: + +- If $k = 0$, it means we do not hold any stock. +- If $k = 1$, it means we are holding a stock. +- If $k = 2$, it means we are holding a short position. + +Initially, for any $j \in [1, k]$, we have $f[0][j][1] = -prices[0]$ and $f[0][j][2] = prices[0]$. This means buying a stock or opening a short position on day 0. + +Next, we update $f[i][j][k]$ using state transitions. For each day $i$ and each transaction $j$, we update according to the current state $k$: + +- If $k = 0$, meaning no stock is held, this state can be reached from three situations: + - No stock was held the previous day. + - A stock was held the previous day and sold today. + - A short position was held the previous day and bought back today. +- If $k = 1$, meaning a stock is held, this state can be reached from two situations: + - A stock was held the previous day. + - No stock was held the previous day and a stock is bought today. +- If $k = 2$, meaning a short position is held, this state can be reached from two situations: + - A short position was held the previous day. + - No stock was held the previous day and a short position is opened (sold) today. + +That is, for $1 \leq i < n$ and $1 \leq j \leq k$, we have the following state transition equations: + +$$ +\begin{aligned} +f[i][j][0] &= \max(f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]) \\ +f[i][j][1] &= \max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]) \\ +f[i][j][2] &= \max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]) +\end{aligned} +$$ + +Finally, we return $f[n - 1][k][0]$, which is the maximum profit after at most $k$ transactions and not holding any stock at the end of $n$ days. + +The time complexity is $O(n \times k)$, and the space complexity is $O(n \times k)$, where $n$ is the length of the array $\textit{prices}$ and $k$ is the maximum number of transactions. #### Python3 ```python - +class Solution: + def maximumProfit(self, prices: List[int], k: int) -> int: + n = len(prices) + f = [[[0] * 3 for _ in range(k + 1)] for _ in range(n)] + for j in range(1, k + 1): + f[0][j][1] = -prices[0] + f[0][j][2] = prices[0] + for i in range(1, n): + for j in range(1, k + 1): + f[i][j][0] = max( + f[i - 1][j][0], + f[i - 1][j][1] + prices[i], + f[i - 1][j][2] - prices[i], + ) + f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]) + f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]) + return f[n - 1][k][0] ``` #### Java ```java - +class Solution { + public long maximumProfit(int[] prices, int k) { + int n = prices.length; + long[][][] f = new long[n][k + 1][3]; + for (int j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + for (int i = 1; i < n; ++i) { + for (int j = 1; j <= k; ++j) { + f[i][j][0] = Math.max(f[i - 1][j][0], + Math.max(f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i])); + f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + return f[n - 1][k][0]; + } +} ``` #### C++ ```cpp - +class Solution { +public: + long long maximumProfit(vector& prices, int k) { + int n = prices.size(); + long long f[n][k + 1][3]; + memset(f, 0, sizeof(f)); + for (int j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + + for (int i = 1; i < n; ++i) { + for (int j = 1; j <= k; ++j) { + f[i][j][0] = max({f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]}); + f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + + return f[n - 1][k][0]; + } +}; ``` #### Go ```go +func maximumProfit(prices []int, k int) int64 { + n := len(prices) + f := make([][][3]int, n) + for i := range f { + f[i] = make([][3]int, k+1) + } + + for j := 1; j <= k; j++ { + f[0][j][1] = -prices[0] + f[0][j][2] = prices[0] + } + + for i := 1; i < n; i++ { + for j := 1; j <= k; j++ { + f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1]+prices[i], f[i-1][j][2]-prices[i]) + f[i][j][1] = max(f[i-1][j][1], f[i-1][j-1][0]-prices[i]) + f[i][j][2] = max(f[i-1][j][2], f[i-1][j-1][0]+prices[i]) + } + } + + return int64(f[n-1][k][0]) +} +``` +#### TypeScript + +```ts +function maximumProfit(prices: number[], k: number): number { + const n = prices.length; + const f: number[][][] = Array.from({ length: n }, () => + Array.from({ length: k + 1 }, () => Array(3).fill(0)), + ); + + for (let j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + + for (let i = 1; i < n; ++i) { + for (let j = 1; j <= k; ++j) { + f[i][j][0] = Math.max( + f[i - 1][j][0], + f[i - 1][j][1] + prices[i], + f[i - 1][j][2] - prices[i], + ); + f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + + return f[n - 1][k][0]; +} ``` diff --git a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.cpp b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.cpp new file mode 100644 index 0000000000000..145b7c56f07ed --- /dev/null +++ b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.cpp @@ -0,0 +1,22 @@ +class Solution { +public: + long long maximumProfit(vector& prices, int k) { + int n = prices.size(); + long long f[n][k + 1][3]; + memset(f, 0, sizeof(f)); + for (int j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + + for (int i = 1; i < n; ++i) { + for (int j = 1; j <= k; ++j) { + f[i][j][0] = max({f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]}); + f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + + return f[n - 1][k][0]; + } +}; \ No newline at end of file diff --git a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.go b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.go new file mode 100644 index 0000000000000..7d7304aa8af0d --- /dev/null +++ b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.go @@ -0,0 +1,22 @@ +func maximumProfit(prices []int, k int) int64 { + n := len(prices) + f := make([][][3]int, n) + for i := range f { + f[i] = make([][3]int, k+1) + } + + for j := 1; j <= k; j++ { + f[0][j][1] = -prices[0] + f[0][j][2] = prices[0] + } + + for i := 1; i < n; i++ { + for j := 1; j <= k; j++ { + f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1]+prices[i], f[i-1][j][2]-prices[i]) + f[i][j][1] = max(f[i-1][j][1], f[i-1][j-1][0]-prices[i]) + f[i][j][2] = max(f[i-1][j][2], f[i-1][j-1][0]+prices[i]) + } + } + + return int64(f[n-1][k][0]) +} \ No newline at end of file diff --git a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.java b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.java new file mode 100644 index 0000000000000..27b58ca1cbaf6 --- /dev/null +++ b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.java @@ -0,0 +1,19 @@ +class Solution { + public long maximumProfit(int[] prices, int k) { + int n = prices.length; + long[][][] f = new long[n][k + 1][3]; + for (int j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + for (int i = 1; i < n; ++i) { + for (int j = 1; j <= k; ++j) { + f[i][j][0] = Math.max(f[i - 1][j][0], + Math.max(f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i])); + f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + return f[n - 1][k][0]; + } +} \ No newline at end of file diff --git a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.py b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.py new file mode 100644 index 0000000000000..d376e65fd756f --- /dev/null +++ b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.py @@ -0,0 +1,17 @@ +class Solution: + def maximumProfit(self, prices: List[int], k: int) -> int: + n = len(prices) + f = [[[0] * 3 for _ in range(k + 1)] for _ in range(n)] + for j in range(1, k + 1): + f[0][j][1] = -prices[0] + f[0][j][2] = prices[0] + for i in range(1, n): + for j in range(1, k + 1): + f[i][j][0] = max( + f[i - 1][j][0], + f[i - 1][j][1] + prices[i], + f[i - 1][j][2] - prices[i], + ) + f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]) + f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]) + return f[n - 1][k][0] diff --git a/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.ts b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.ts new file mode 100644 index 0000000000000..2fd3cd345bc49 --- /dev/null +++ b/solution/3500-3599/3573.Best Time to Buy and Sell Stock V/Solution.ts @@ -0,0 +1,25 @@ +function maximumProfit(prices: number[], k: number): number { + const n = prices.length; + const f: number[][][] = Array.from({ length: n }, () => + Array.from({ length: k + 1 }, () => Array(3).fill(0)), + ); + + for (let j = 1; j <= k; ++j) { + f[0][j][1] = -prices[0]; + f[0][j][2] = prices[0]; + } + + for (let i = 1; i < n; ++i) { + for (let j = 1; j <= k; ++j) { + f[i][j][0] = Math.max( + f[i - 1][j][0], + f[i - 1][j][1] + prices[i], + f[i - 1][j][2] - prices[i], + ); + f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]); + f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]); + } + } + + return f[n - 1][k][0]; +}