Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9f04133

Browse files
feat: add solutions to lc problem: No.0309 (#1744)
No.0309.Best Time to Buy and Sell Stock with Cooldown
1 parent 58746c7 commit 9f04133

File tree

7 files changed

+539
-139
lines changed

7 files changed

+539
-139
lines changed

‎solution/0300-0399/0309.Best Time to Buy and Sell Stock with Cooldown/README.md‎

Lines changed: 262 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,33 @@
4545

4646
<!-- 这里可写通用的实现逻辑 -->
4747

48-
动态规划法。
48+
**方法一:记忆化搜索**
4949

50-
设 f1 表示当天买入股票后的最大利润,f2 表示当天卖出股票后的最大利润,f3 表示当天空仓后的最大利润
50+
我们设计一个函数 $dfs(i, j),ドル表示从第 $i$ 天开始,状态为 $j$ 时,能够获得的最大利润。其中 $j$ 的取值为 0,ドル 1,ドル分别表示当前不持有股票和持有股票。答案即为 $dfs(0, 0)$
5151

52-
初始第 1 天结束时,`f1 = -prices[0]`,`f2 = 0`,`f3 = 0`
52+
函数 $dfs(i, j)$ 的执行逻辑如下:
5353

54-
从第 2 天开始,当天结束时:
54+
如果 $i \geq n,ドル表示已经没有股票可以交易了,此时返回 0ドル$;
5555

56-
- 若买入,则说明前一天空仓,然后今天买入,`f1 = max(f1, f3 - prices[i])`
57-
- 若卖出,则只能是之前某一天买入,然后今天卖出,`f2 = max(f2, f1 + prices[i])`
58-
- 若空仓,则只能是之前某一天卖出后,然后今天保持空仓,`f3 = max(f3, f2)`
56+
否则,我们可以选择不交易,此时 $dfs(i, j) = dfs(i + 1, j)$。我们也可以进行股票交易,如果此时 $j \gt 0,ドル说明当前持有股票,可以卖出,此时 $dfs(i, j) = prices[i] + dfs(i + 2, 0)$;如果此时 $j = 0,ドル说明当前不持有股票,可以买入,此时 $dfs(i, j) = -prices[i] + dfs(i + 1, 1)$。取最大值作为函数 $dfs(i, j)$ 的返回值。
5957

60-
最后返回 f2 即可。
58+
答案为 $dfs(0, 0)$。
59+
60+
为了避免重复计算,我们使用记忆化搜索的方法,用一个数组 $f$ 记录 $dfs(i, j)$ 的返回值,如果 $f[i][j]$ 不为 $-1,ドル说明已经计算过,直接返回 $f[i][j]$ 即可。
61+
62+
时间复杂度 $O(n),ドル空间复杂度 $O(n)$。其中 $n$ 为数组 $prices$ 的长度。
63+
64+
**方法二:动态规划**
65+
66+
我们也可以用动态规划的方法求解。
67+
68+
我们定义 $f[i][j]$ 表示到第 $i$ 天,且状态为 $j$ 时,能够获得的最大利润。其中 $j$ 的取值为 0,ドル 1,ドル分别表示当前不持有股票和持有股票。初始时 $f[0][0] = 0,ドル $f[0][1] = -prices[0]$。
69+
70+
当 $i \geq 1$ 时,如果当前不持有股票,那么 $f[i][0]$ 可以由 $f[i - 1][0]$ 和 $f[i - 1][1] + prices[i]$ 转移得到,即 $f[i][0] = \max(f[i - 1][0], f[i - 1][1] + prices[i])$;如果当前持有股票,那么 $f[i][1]$ 可以由 $f[i - 1][1]$ 和 $f[i - 2][0] - prices[i]$ 转移得到,即 $f[i][1] = \max(f[i - 1][1], f[i - 2][0] - prices[i])$。最终答案为 $f[n - 1][0]$。
71+
72+
时间复杂度 $O(n),ドル空间复杂度 $O(n)$。其中 $n$ 为数组 $prices$ 的长度。
73+
74+
我们注意到,状态 $f[i][]$ 的转移只与 $f[i - 1][]$ 和 $f[i - 2][0]$ 有关,因此我们可以用三个变量 $f, f_0, f_1$ 代替数组 $f,ドル将空间复杂度优化到 $O(1)$。
6175

6276
<!-- tabs:start -->
6377

@@ -68,14 +82,39 @@
6882
```python
6983
class Solution:
7084
def maxProfit(self, prices: List[int]) -> int:
71-
# 买入,卖出,继续空仓
72-
f1, f2, f3 = -prices[0], 0, 0
73-
for price in prices[1:]:
74-
pf1, pf2, pf3 = f1, f2, f3
75-
f1 = max(pf1, pf3 - price)
76-
f2 = max(pf2, pf1 + price)
77-
f3 = max(pf3, pf2)
78-
return f2
85+
@cache
86+
def dfs(i: int, j: int) -> int:
87+
if i >= len(prices):
88+
return 0
89+
ans = dfs(i + 1, j)
90+
if j:
91+
ans = max(ans, prices[i] + dfs(i + 2, 0))
92+
else:
93+
ans = max(ans, -prices[i] + dfs(i + 1, 1))
94+
return ans
95+
96+
return dfs(0, 0)
97+
```
98+
99+
```python
100+
class Solution:
101+
def maxProfit(self, prices: List[int]) -> int:
102+
n = len(prices)
103+
f = [[0] * 2 for _ in range(n)]
104+
f[0][1] = -prices[0]
105+
for i in range(1, n):
106+
f[i][0] = max(f[i - 1][0], f[i - 1][1] + prices[i])
107+
f[i][1] = max(f[i - 1][1], f[i - 2][0] - prices[i])
108+
return f[n - 1][0]
109+
```
110+
111+
```python
112+
class Solution:
113+
def maxProfit(self, prices: List[int]) -> int:
114+
f, f0, f1 = 0, 0, -prices[0]
115+
for x in prices[1:]:
116+
f, f0, f1 = f0, max(f0, f1 + x), max(f1, f - x)
117+
return f0
79118
```
80119

81120
### **Java**
@@ -84,35 +123,60 @@ class Solution:
84123

85124
```java
86125
class Solution {
126+
private int[] prices;
127+
private Integer[][] f;
128+
87129
public int maxProfit(int[] prices) {
88-
// 买入,卖出,继续空仓
89-
int f1 = -prices[0], f2 = 0, f3 = 0;
90-
for (int i = 1; i < prices.length; ++i) {
91-
int pf1 = f1, pf2 = f2, pf3 = f3;
92-
f1 = Math.max(pf1, pf3 - prices[i]);
93-
f2 = Math.max(pf2, pf1 + prices[i]);
94-
f3 = Math.max(pf3, pf2);
130+
this.prices = prices;
131+
f = new Integer[prices.length][2];
132+
return dfs(0, 0);
133+
}
134+
135+
private int dfs(int i, int j) {
136+
if (i >= prices.length) {
137+
return 0;
138+
}
139+
if (f[i][j] != null) {
140+
return f[i][j];
141+
}
142+
int ans = dfs(i + 1, j);
143+
if (j > 0) {
144+
ans = Math.max(ans, prices[i] + dfs(i + 2, 0));
145+
} else {
146+
ans = Math.max(ans, -prices[i] + dfs(i + 1, 1));
95147
}
96-
return f2;
148+
return f[i][j] = ans;
97149
}
98150
}
99151
```
100152

101-
### **TypeScript**
153+
```java
154+
class Solution {
155+
public int maxProfit(int[] prices) {
156+
int n = prices.length;
157+
int[][] f = new int[n][2];
158+
f[0][1] = -prices[0];
159+
for (int i = 1; i < n; i++) {
160+
f[i][0] = Math.max(f[i - 1][0], f[i - 1][1] + prices[i]);
161+
f[i][1] = Math.max(f[i - 1][1], (i > 1 ? f[i - 2][0] : 0) - prices[i]);
162+
}
163+
return f[n - 1][0];
164+
}
165+
}
166+
```
102167

103-
```ts
104-
function maxProfit(prices:number[]):number {
105-
const n = prices.length;
106-
let dp =Array.from({ length: n }, v=>newArray(3).fill(0));
107-
dp[0] = [0, -prices[0], Number.MIN_SAFE_INTEGER];
108-
for (let i =1; i<n; i++) {
109-
dp[i] = [
110-
Math.max(dp[i-1][0], dp[i-1][2]),
111-
Math.max(dp[i-1][1], dp[i-1][0] -prices[i]),
112-
dp[i-1][1] +prices[i],
113-
];
168+
```java
169+
classSolution {
170+
publicintmaxProfit(int[] prices) {
171+
int f =0, f0 =0, f1 =-prices[0];
172+
for (int i =1; i < prices.length; ++i) {
173+
int g0 =Math.max(f0, f1 + prices[i]);
174+
f1 =Math.max(f1, f - prices[i]);
175+
f = f0;
176+
f0 = g0;
177+
}
178+
return f0;
114179
}
115-
return Math.max(dp[n - 1][0], dp[n - 1][2]);
116180
}
117181
```
118182

@@ -122,14 +186,58 @@ function maxProfit(prices: number[]): number {
122186
class Solution {
123187
public:
124188
int maxProfit(vector<int>& prices) {
125-
int f1 = -prices[0], f2 = 0, f3 = 0;
189+
int n = prices.size();
190+
int f[n][2];
191+
memset(f, -1, sizeof(f));
192+
function<int(int, int)> dfs = [&](int i, int j) {
193+
if (i >= n) {
194+
return 0;
195+
}
196+
if (f[i][j] != -1) {
197+
return f[i][j];
198+
}
199+
int ans = dfs(i + 1, j);
200+
if (j) {
201+
ans = max(ans, prices[i] + dfs(i + 2, 0));
202+
} else {
203+
ans = max(ans, -prices[i] + dfs(i + 1, 1));
204+
}
205+
return f[i][j] = ans;
206+
};
207+
return dfs(0, 0);
208+
}
209+
};
210+
```
211+
212+
```cpp
213+
class Solution {
214+
public:
215+
int maxProfit(vector<int>& prices) {
216+
int n = prices.size();
217+
int f[n][2];
218+
memset(f, 0, sizeof(f));
219+
f[0][1] = -prices[0];
220+
for (int i = 1; i < n; ++i) {
221+
f[i][0] = max(f[i - 1][0], f[i - 1][1] + prices[i]);
222+
f[i][1] = max(f[i - 1][1], (i > 1 ? f[i - 2][0] : 0) - prices[i]);
223+
}
224+
return f[n - 1][0];
225+
}
226+
};
227+
```
228+
229+
```cpp
230+
class Solution {
231+
public:
232+
int maxProfit(vector<int>& prices) {
233+
int f = 0, f0 = 0, f1 = -prices[0];
126234
for (int i = 1; i < prices.size(); ++i) {
127-
int pf1 = f1, pf2 = f2, pf3 = f3;
128-
f1 = max(pf1, pf3 - prices[i]);
129-
f2 = max(pf2, pf1 + prices[i]);
130-
f3 = max(pf3, pf2);
235+
int g0 = max(f0, f1 + prices[i]);
236+
f1 = max(f1, f - prices[i]);
237+
f = f0;
238+
f0 = g0;
131239
}
132-
return f2;
240+
return f0;
133241
}
134242
};
135243
```
@@ -138,14 +246,70 @@ public:
138246
139247
```go
140248
func maxProfit(prices []int) int {
141-
f1, f2, f3 := -prices[0], 0, 0
142-
for i := 1; i < len(prices); i++ {
143-
pf1, pf2, pf3 := f1, f2, f3
144-
f1 = max(pf1, pf3-prices[i])
145-
f2 = max(pf2, pf1+prices[i])
146-
f3 = max(pf3, pf2)
249+
n := len(prices)
250+
f := make([][2]int, n)
251+
for i := range f {
252+
f[i] = [2]int{-1, -1}
253+
}
254+
var dfs func(i, j int) int
255+
dfs = func(i, j int) int {
256+
if i >= n {
257+
return 0
258+
}
259+
if f[i][j] != -1 {
260+
return f[i][j]
261+
}
262+
ans := dfs(i+1, j)
263+
if j > 0 {
264+
ans = max(ans, prices[i]+dfs(i+2, 0))
265+
} else {
266+
ans = max(ans, -prices[i]+dfs(i+1, 1))
267+
}
268+
f[i][j] = ans
269+
return ans
270+
}
271+
return dfs(0, 0)
272+
}
273+
274+
func max(a, b int) int {
275+
if a > b {
276+
return a
277+
}
278+
return b
279+
}
280+
```
281+
282+
```go
283+
func maxProfit(prices []int) int {
284+
n := len(prices)
285+
f := make([][2]int, n)
286+
f[0][1] = -prices[0]
287+
for i := 1; i < n; i++ {
288+
f[i][0] = max(f[i-1][0], f[i-1][1]+prices[i])
289+
if i > 1 {
290+
f[i][1] = max(f[i-1][1], f[i-2][0]-prices[i])
291+
} else {
292+
f[i][1] = max(f[i-1][1], -prices[i])
293+
}
294+
}
295+
return f[n-1][0]
296+
}
297+
298+
func max(a, b int) int {
299+
if a > b {
300+
return a
301+
}
302+
return b
303+
}
304+
```
305+
306+
```go
307+
func maxProfit(prices []int) int {
308+
f, f0, f1 := 0, 0, -prices[0]
309+
for _, x := range prices[1:] {
310+
f, f0, f1 = f0, max(f0, f1+x), max(f1, f-x)
147311
}
148-
return f2
312+
return f0
149313
}
150314

151315
func max(a, b int) int {
@@ -156,6 +320,54 @@ func max(a, b int) int {
156320
}
157321
```
158322

323+
### **TypeScript**
324+
325+
```ts
326+
function maxProfit(prices: number[]): number {
327+
const n = prices.length;
328+
const f: number[][] = Array.from({ length: n }, () => Array.from({ length: 2 }, () => -1));
329+
const dfs = (i: number, j: number): number => {
330+
if (i >= n) {
331+
return 0;
332+
}
333+
if (f[i][j] !== -1) {
334+
return f[i][j];
335+
}
336+
let ans = dfs(i + 1, j);
337+
if (j) {
338+
ans = Math.max(ans, prices[i] + dfs(i + 2, 0));
339+
} else {
340+
ans = Math.max(ans, -prices[i] + dfs(i + 1, 1));
341+
}
342+
return (f[i][j] = ans);
343+
};
344+
return dfs(0, 0);
345+
}
346+
```
347+
348+
```ts
349+
function maxProfit(prices: number[]): number {
350+
const n = prices.length;
351+
const f: number[][] = Array.from({ length: n }, () => Array.from({ length: 2 }, () => 0));
352+
f[0][1] = -prices[0];
353+
for (let i = 1; i < n; ++i) {
354+
f[i][0] = Math.max(f[i - 1][0], f[i - 1][1] + prices[i]);
355+
f[i][1] = Math.max(f[i - 1][1], (i > 1 ? f[i - 2][0] : 0) - prices[i]);
356+
}
357+
return f[n - 1][0];
358+
}
359+
```
360+
361+
```ts
362+
function maxProfit(prices: number[]): number {
363+
let [f, f0, f1] = [0, 0, -prices[0]];
364+
for (const x of prices.slice(1)) {
365+
[f, f0, f1] = [f0, Math.max(f0, f1 + x), Math.max(f1, f - x)];
366+
}
367+
return f0;
368+
}
369+
```
370+
159371
### **...**
160372

161373
```

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /