45
45
46
46
<!-- 这里可写通用的实现逻辑 -->
47
47
48
- 动态规划法。
48
+ ** 方法一:记忆化搜索 **
49
49
50
- 设 f1 表示当天买入股票后的最大利润,f2 表示当天卖出股票后的最大利润,f3 表示当天空仓后的最大利润 。
50
+ 我们设计一个函数 $dfs(i, j)$,表示从第 $i$ 天开始,状态为 $j$ 时,能够获得的最大利润。其中 $j$ 的取值为 $0, 1$,分别表示当前不持有股票和持有股票。答案即为 $dfs(0, 0)$ 。
51
51
52
- 初始第 1 天结束时, ` f1 = -prices[0] ` , ` f2 = 0 ` , ` f3 = 0 ` 。
52
+ 函数 $dfs(i, j)$ 的执行逻辑如下:
53
53
54
- 从第 2 天开始,当天结束时:
54
+ 如果 $i \geq n$,表示已经没有股票可以交易了,此时返回 $0$;
55
55
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)$ 的返回值。
59
57
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)$。
61
75
62
76
<!-- tabs:start -->
63
77
68
82
``` python
69
83
class Solution :
70
84
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
79
118
```
80
119
81
120
### ** Java**
@@ -84,35 +123,60 @@ class Solution:
84
123
85
124
``` java
86
125
class Solution {
126
+ private int [] prices;
127
+ private Integer [][] f;
128
+
87
129
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 ));
95
147
}
96
- return f2 ;
148
+ return f[i][j] = ans ;
97
149
}
98
150
}
99
151
```
100
152
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
+ ```
102
167
103
- ``` ts
104
- function maxProfit( prices : number []) : number {
105
- const n = prices . length ;
106
- let dp = Array . from ({ length: n }, v => new Array ( 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
+ class Solution {
170
+ public int maxProfit ( 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 ;
114
179
}
115
- return Math .max (dp [n - 1 ][0 ], dp [n - 1 ][2 ]);
116
180
}
117
181
```
118
182
@@ -122,14 +186,58 @@ function maxProfit(prices: number[]): number {
122
186
class Solution {
123
187
public:
124
188
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] ;
126
234
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 ;
131
239
}
132
- return f2 ;
240
+ return f0 ;
133
241
}
134
242
};
135
243
```
@@ -138,14 +246,70 @@ public:
138
246
139
247
```go
140
248
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)
147
311
}
148
- return f2
312
+ return f0
149
313
}
150
314
151
315
func max (a , b int ) int {
@@ -156,6 +320,54 @@ func max(a, b int) int {
156
320
}
157
321
```
158
322
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
+
159
371
### ** ...**
160
372
161
373
```
0 commit comments