Skip to content

Commit f5db36b

Browse files
authored
feat: add solutions to lc problem: No.3573 (#4468)
No.3573.Best Time to Buy and Sell Stock V
1 parent 078c02d commit f5db36b

File tree

7 files changed

+395
-8
lines changed

7 files changed

+395
-8
lines changed

solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README.md

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,32 +82,173 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3573.Be
8282

8383
<!-- solution:start -->
8484

85-
### 方法一
85+
### 方法一:动态规划
86+
87+
我们定义 $f[i][j][k]$ 表示在前 $i$ 天内,最多进行 $j$ 笔交易,且当前状态为 $k$ 时的最大利润。这里的状态 $k$ 有三种可能:
88+
89+
- 若 $k = 0$,表示当前没有持有股票。
90+
- 若 $k = 1$,表示当前持有一支股票。
91+
- 若 $k = 2$,表示当前持有一支股票的空头。
92+
93+
初始时,对任意 $j \in [1, k]$,都有 $f[0][j][1] = -prices[0]$ 和 $f[0][j][2] = prices[0]$。这表示在第 0 天买入一支股票或卖出一支股票的空头。
94+
95+
接下来,我们可以通过状态转移来更新 $f[i][j][k]$ 的值。对于每一天 $i$ 和每笔交易 $j$,我们可以根据当前状态 $k$ 来决定如何更新:
96+
97+
- 若 $k = 0$,表示当前没有持有股票,这个状态可以由以下三种情况转移而来:
98+
- 前一天没有持有股票。
99+
- 前一天持有一支股票,并在今天卖出。
100+
- 前一天持有一支股票的空头,并在今天买回。
101+
- 若 $k = 1$,表示当前持有一支股票,这个状态可以由以下两种情况转移而来:
102+
- 前一天持有一支股票。
103+
- 前一天没有持有股票,并在今天买入。
104+
- 若 $k = 2$,表示当前持有一支股票的空头,这个状态可以由以下两种情况转移而来:
105+
- 前一天持有一支股票的空头。
106+
- 前一天没有持有股票,并在今天卖出。
107+
108+
即,对于 $1 \leq i < n$ 和 $1 \leq j \leq k$,我们有以下状态转移方程:
109+
110+
$$
111+
\begin{aligned}
112+
f[i][j][0] &= \max(f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]) \\
113+
f[i][j][1] &= \max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]) \\
114+
f[i][j][2] &= \max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i])
115+
\end{aligned}
116+
$$
117+
118+
最终,我们需要返回 $f[n - 1][k][0]$,即在前 $n$ 天内,最多进行 $k$ 笔交易,且当前没有持有股票时的最大利润。
119+
120+
时间复杂度 $O(n \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 为数组 $\textit{prices}$ 的长度,而 $k$ 为最大交易次数。
86121

87122
<!-- tabs:start -->
88123

89124
#### Python3
90125

91126
```python
92-
127+
class Solution:
128+
def maximumProfit(self, prices: List[int], k: int) -> int:
129+
n = len(prices)
130+
f = [[[0] * 3 for _ in range(k + 1)] for _ in range(n)]
131+
for j in range(1, k + 1):
132+
f[0][j][1] = -prices[0]
133+
f[0][j][2] = prices[0]
134+
for i in range(1, n):
135+
for j in range(1, k + 1):
136+
f[i][j][0] = max(
137+
f[i - 1][j][0],
138+
f[i - 1][j][1] + prices[i],
139+
f[i - 1][j][2] - prices[i],
140+
)
141+
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i])
142+
f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i])
143+
return f[n - 1][k][0]
93144
```
94145

95146
#### Java
96147

97148
```java
98-
149+
class Solution {
150+
public long maximumProfit(int[] prices, int k) {
151+
int n = prices.length;
152+
long[][][] f = new long[n][k + 1][3];
153+
for (int j = 1; j <= k; ++j) {
154+
f[0][j][1] = -prices[0];
155+
f[0][j][2] = prices[0];
156+
}
157+
for (int i = 1; i < n; ++i) {
158+
for (int j = 1; j <= k; ++j) {
159+
f[i][j][0] = Math.max(f[i - 1][j][0],
160+
Math.max(f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]));
161+
f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]);
162+
f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]);
163+
}
164+
}
165+
return f[n - 1][k][0];
166+
}
167+
}
99168
```
100169

101170
#### C++
102171

103172
```cpp
104-
173+
class Solution {
174+
public:
175+
long long maximumProfit(vector<int>& prices, int k) {
176+
int n = prices.size();
177+
long long f[n][k + 1][3];
178+
memset(f, 0, sizeof(f));
179+
for (int j = 1; j <= k; ++j) {
180+
f[0][j][1] = -prices[0];
181+
f[0][j][2] = prices[0];
182+
}
183+
184+
for (int i = 1; i < n; ++i) {
185+
for (int j = 1; j <= k; ++j) {
186+
f[i][j][0] = max({f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]});
187+
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]);
188+
f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]);
189+
}
190+
}
191+
192+
return f[n - 1][k][0];
193+
}
194+
};
105195
```
106196

107197
#### Go
108198

109199
```go
200+
func maximumProfit(prices []int, k int) int64 {
201+
n := len(prices)
202+
f := make([][][3]int, n)
203+
for i := range f {
204+
f[i] = make([][3]int, k+1)
205+
}
206+
207+
for j := 1; j <= k; j++ {
208+
f[0][j][1] = -prices[0]
209+
f[0][j][2] = prices[0]
210+
}
211+
212+
for i := 1; i < n; i++ {
213+
for j := 1; j <= k; j++ {
214+
f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1]+prices[i], f[i-1][j][2]-prices[i])
215+
f[i][j][1] = max(f[i-1][j][1], f[i-1][j-1][0]-prices[i])
216+
f[i][j][2] = max(f[i-1][j][2], f[i-1][j-1][0]+prices[i])
217+
}
218+
}
219+
220+
return int64(f[n-1][k][0])
221+
}
222+
```
110223

224+
#### TypeScript
225+
226+
```ts
227+
function maximumProfit(prices: number[], k: number): number {
228+
const n = prices.length;
229+
const f: number[][][] = Array.from({ length: n }, () =>
230+
Array.from({ length: k + 1 }, () => Array(3).fill(0)),
231+
);
232+
233+
for (let j = 1; j <= k; ++j) {
234+
f[0][j][1] = -prices[0];
235+
f[0][j][2] = prices[0];
236+
}
237+
238+
for (let i = 1; i < n; ++i) {
239+
for (let j = 1; j <= k; ++j) {
240+
f[i][j][0] = Math.max(
241+
f[i - 1][j][0],
242+
f[i - 1][j][1] + prices[i],
243+
f[i - 1][j][2] - prices[i],
244+
);
245+
f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]);
246+
f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]);
247+
}
248+
}
249+
250+
return f[n - 1][k][0];
251+
}
111252
```
112253

113254
<!-- tabs:end -->

solution/3500-3599/3573.Best Time to Buy and Sell Stock V/README_EN.md

Lines changed: 145 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,32 +80,173 @@ We can make $36 of profit through 3 transactions:
8080

8181
<!-- solution:start -->
8282

83-
### Solution 1
83+
### Solution 1: Dynamic Programming
84+
85+
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:
86+
87+
- If $k = 0$, it means we do not hold any stock.
88+
- If $k = 1$, it means we are holding a stock.
89+
- If $k = 2$, it means we are holding a short position.
90+
91+
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.
92+
93+
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$:
94+
95+
- If $k = 0$, meaning no stock is held, this state can be reached from three situations:
96+
- No stock was held the previous day.
97+
- A stock was held the previous day and sold today.
98+
- A short position was held the previous day and bought back today.
99+
- If $k = 1$, meaning a stock is held, this state can be reached from two situations:
100+
- A stock was held the previous day.
101+
- No stock was held the previous day and a stock is bought today.
102+
- If $k = 2$, meaning a short position is held, this state can be reached from two situations:
103+
- A short position was held the previous day.
104+
- No stock was held the previous day and a short position is opened (sold) today.
105+
106+
That is, for $1 \leq i < n$ and $1 \leq j \leq k$, we have the following state transition equations:
107+
108+
$$
109+
\begin{aligned}
110+
f[i][j][0] &= \max(f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]) \\
111+
f[i][j][1] &= \max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]) \\
112+
f[i][j][2] &= \max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i])
113+
\end{aligned}
114+
$$
115+
116+
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.
117+
118+
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.
84119

85120
<!-- tabs:start -->
86121

87122
#### Python3
88123

89124
```python
90-
125+
class Solution:
126+
def maximumProfit(self, prices: List[int], k: int) -> int:
127+
n = len(prices)
128+
f = [[[0] * 3 for _ in range(k + 1)] for _ in range(n)]
129+
for j in range(1, k + 1):
130+
f[0][j][1] = -prices[0]
131+
f[0][j][2] = prices[0]
132+
for i in range(1, n):
133+
for j in range(1, k + 1):
134+
f[i][j][0] = max(
135+
f[i - 1][j][0],
136+
f[i - 1][j][1] + prices[i],
137+
f[i - 1][j][2] - prices[i],
138+
)
139+
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i])
140+
f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i])
141+
return f[n - 1][k][0]
91142
```
92143

93144
#### Java
94145

95146
```java
96-
147+
class Solution {
148+
public long maximumProfit(int[] prices, int k) {
149+
int n = prices.length;
150+
long[][][] f = new long[n][k + 1][3];
151+
for (int j = 1; j <= k; ++j) {
152+
f[0][j][1] = -prices[0];
153+
f[0][j][2] = prices[0];
154+
}
155+
for (int i = 1; i < n; ++i) {
156+
for (int j = 1; j <= k; ++j) {
157+
f[i][j][0] = Math.max(f[i - 1][j][0],
158+
Math.max(f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]));
159+
f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]);
160+
f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]);
161+
}
162+
}
163+
return f[n - 1][k][0];
164+
}
165+
}
97166
```
98167

99168
#### C++
100169

101170
```cpp
102-
171+
class Solution {
172+
public:
173+
long long maximumProfit(vector<int>& prices, int k) {
174+
int n = prices.size();
175+
long long f[n][k + 1][3];
176+
memset(f, 0, sizeof(f));
177+
for (int j = 1; j <= k; ++j) {
178+
f[0][j][1] = -prices[0];
179+
f[0][j][2] = prices[0];
180+
}
181+
182+
for (int i = 1; i < n; ++i) {
183+
for (int j = 1; j <= k; ++j) {
184+
f[i][j][0] = max({f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]});
185+
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]);
186+
f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]);
187+
}
188+
}
189+
190+
return f[n - 1][k][0];
191+
}
192+
};
103193
```
104194

105195
#### Go
106196

107197
```go
198+
func maximumProfit(prices []int, k int) int64 {
199+
n := len(prices)
200+
f := make([][][3]int, n)
201+
for i := range f {
202+
f[i] = make([][3]int, k+1)
203+
}
204+
205+
for j := 1; j <= k; j++ {
206+
f[0][j][1] = -prices[0]
207+
f[0][j][2] = prices[0]
208+
}
209+
210+
for i := 1; i < n; i++ {
211+
for j := 1; j <= k; j++ {
212+
f[i][j][0] = max(f[i-1][j][0], f[i-1][j][1]+prices[i], f[i-1][j][2]-prices[i])
213+
f[i][j][1] = max(f[i-1][j][1], f[i-1][j-1][0]-prices[i])
214+
f[i][j][2] = max(f[i-1][j][2], f[i-1][j-1][0]+prices[i])
215+
}
216+
}
217+
218+
return int64(f[n-1][k][0])
219+
}
220+
```
108221

222+
#### TypeScript
223+
224+
```ts
225+
function maximumProfit(prices: number[], k: number): number {
226+
const n = prices.length;
227+
const f: number[][][] = Array.from({ length: n }, () =>
228+
Array.from({ length: k + 1 }, () => Array(3).fill(0)),
229+
);
230+
231+
for (let j = 1; j <= k; ++j) {
232+
f[0][j][1] = -prices[0];
233+
f[0][j][2] = prices[0];
234+
}
235+
236+
for (let i = 1; i < n; ++i) {
237+
for (let j = 1; j <= k; ++j) {
238+
f[i][j][0] = Math.max(
239+
f[i - 1][j][0],
240+
f[i - 1][j][1] + prices[i],
241+
f[i - 1][j][2] - prices[i],
242+
);
243+
f[i][j][1] = Math.max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]);
244+
f[i][j][2] = Math.max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]);
245+
}
246+
}
247+
248+
return f[n - 1][k][0];
249+
}
109250
```
110251

111252
<!-- tabs:end -->
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Solution {
2+
public:
3+
long long maximumProfit(vector<int>& prices, int k) {
4+
int n = prices.size();
5+
long long f[n][k + 1][3];
6+
memset(f, 0, sizeof(f));
7+
for (int j = 1; j <= k; ++j) {
8+
f[0][j][1] = -prices[0];
9+
f[0][j][2] = prices[0];
10+
}
11+
12+
for (int i = 1; i < n; ++i) {
13+
for (int j = 1; j <= k; ++j) {
14+
f[i][j][0] = max({f[i - 1][j][0], f[i - 1][j][1] + prices[i], f[i - 1][j][2] - prices[i]});
15+
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j - 1][0] - prices[i]);
16+
f[i][j][2] = max(f[i - 1][j][2], f[i - 1][j - 1][0] + prices[i]);
17+
}
18+
}
19+
20+
return f[n - 1][k][0];
21+
}
22+
};

0 commit comments

Comments
 (0)