49
49
50
50
<!-- 这里可写通用的实现逻辑 -->
51
51
52
- 动态规划法。
52
+ ** 方法一:记忆化搜索 **
53
53
54
- 设 f1 表示当天持有股票的最大利润,f2 表示当天没持有股票的最大利润 。
54
+ 我们设计一个函数 $dfs(i, j)$,表示从第 $i$ 天开始,状态为 $j$ 时,能够获得的最大利润。其中 $j$ 的取值为 $0, 1$,分别表示当前不持有股票和持有股票。答案即为 $dfs(0, 0)$ 。
55
55
56
- 初始第 1 天结束时, ` f1 = -prices[0] ` , ` f2 = 0 ` 。
56
+ 函数 $dfs(i, j)$ 的执行逻辑如下:
57
57
58
- 从第 2 天开始,当天结束时:
58
+ 如果 $i \geq n$,那么没有股票可以交易了,此时返回 $0$;
59
59
60
- - 若持有,则可能是前一天持有,今天继续持有;也可能前一天没持有,今天买入,` f1 = max(f1, f2 - price) ` 。
61
- - 若没持有,则可能是前一天持有,今天卖出;也可能是前一天没没有,今天继续没持有,` f2 = max(f2, f1 + price - fee) ` 。
60
+ 否则,我们可以选择不交易,此时 $dfs(i, j) = dfs(i + 1, j)$。我们也可以进行股票交易,如果此时 $j \gt 0$,说明当前持有股票,可以卖出,此时 $dfs(i, j) = prices[ i] + dfs(i + 1, 0) - fee$;如果此时 $j = 0$,说明当前不持有股票,可以买入,此时 $dfs(i, j) = -prices[ i] + dfs(i + 1, 1)$。取最大值作为函数 $dfs(i, j)$ 的返回值。
62
61
63
- 最后返回 f2 即可。
62
+ 答案为 $dfs(0, 0)$。
63
+
64
+ 为了避免重复计算,我们使用记忆化搜索的方法,用一个数组 $f$ 记录 $dfs(i, j)$ 的返回值,如果 $f[ i] [ j ] $ 不为 $-1$,说明已经计算过,直接返回 $f[ i] [ j ] $ 即可。
65
+
66
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $prices$ 的长度。
67
+
68
+ ** 方法二:动态规划**
69
+
70
+ 我们定义 $f[ i] [ j ] $ 表示到第 $i$ 天,且状态为 $j$ 时,能够获得的最大利润。其中 $j$ 的取值为 $0, 1$,分别表示当前不持有股票和持有股票。初始时 $f[ 0] [ 0 ] = 0$, $f[ 0] [ 1 ] = -prices[ 0] $。
71
+
72
+ 当 $i \geq 1$ 时,如果当前不持有股票,那么 $f[ i] [ 0 ] $ 可以由 $f[ i - 1] [ 0 ] $ 和 $f[ i - 1] [ 1 ] + prices[ i] - fee$ 转移得到,即 $f[ i] [ 0 ] = \max(f[ i - 1] [ 0 ] , f[ i - 1] [ 1 ] + prices[ i] - fee)$;如果当前持有股票,那么 $f[ i] [ 1 ] $ 可以由 $f[ i - 1] [ 1 ] $ 和 $f[ i - 1] [ 0 ] - prices[ i] $ 转移得到,即 $f[ i] [ 1 ] = \max(f[ i - 1] [ 1 ] , f[ i - 1] [ 0 ] - prices[ i] )$。最终答案为 $f[ n - 1] [ 0 ] $。
73
+
74
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $prices$ 的长度。
75
+
76
+ 我们注意到,状态 $f[ i] [ ] $ 的转移只与 $f[ i - 1] [ ] $ 和 $f[ i - 1] [ ] $ 有关,因此我们可以用两个变量 $f_0, f_1$ 代替数组 $f$,将空间复杂度优化到 $O(1)$。
64
77
65
78
<!-- tabs:start -->
66
79
71
84
``` python
72
85
class Solution :
73
86
def maxProfit (self , prices : List[int ], fee : int ) -> int :
74
- # 持有,没持有
75
- f1, f2 = - prices[0 ], 0
76
- for price in prices[1 :]:
77
- f1 = max (f1, f2 - price)
78
- f2 = max (f2, f1 + price - fee)
79
- return f2
87
+ @cache
88
+ def dfs (i : int , j : int ) -> int :
89
+ if i >= len (prices):
90
+ return 0
91
+ ans = dfs(i + 1 , j)
92
+ if j:
93
+ ans = max (ans, prices[i] + dfs(i + 1 , 0 ) - fee)
94
+ else :
95
+ ans = max (ans, - prices[i] + dfs(i + 1 , 1 ))
96
+ return ans
97
+
98
+ return dfs(0 , 0 )
99
+ ```
100
+
101
+ ``` python
102
+ class Solution :
103
+ def maxProfit (self , prices : List[int ], fee : int ) -> int :
104
+ n = len (prices)
105
+ f = [[0 ] * 2 for _ in range (n)]
106
+ f[0 ][1 ] = - prices[0 ]
107
+ for i in range (1 , n):
108
+ f[i][0 ] = max (f[i - 1 ][0 ], f[i - 1 ][1 ] + prices[i] - fee)
109
+ f[i][1 ] = max (f[i - 1 ][1 ], f[i - 1 ][0 ] - prices[i])
110
+ return f[n - 1 ][0 ]
111
+ ```
112
+
113
+ ``` python
114
+ class Solution :
115
+ def maxProfit (self , prices : List[int ], fee : int ) -> int :
116
+ f0, f1 = 0 , - prices[0 ]
117
+ for x in prices[1 :]:
118
+ f0, f1 = max (f0, f1 + x - fee), max (f1, f0 - x)
119
+ return f0
80
120
```
81
121
82
122
### ** Java**
@@ -85,13 +125,60 @@ class Solution:
85
125
86
126
``` java
87
127
class Solution {
128
+ private Integer [][] f;
129
+ private int [] prices;
130
+ private int fee;
131
+
88
132
public int maxProfit (int [] prices , int fee ) {
89
- int f1 = - prices[0 ], f2 = 0 ;
133
+ f = new Integer [prices. length][2 ];
134
+ this . prices = prices;
135
+ this . fee = fee;
136
+ return dfs(0 , 0 );
137
+ }
138
+
139
+ private int dfs (int i , int j ) {
140
+ if (i >= prices. length) {
141
+ return 0 ;
142
+ }
143
+ if (f[i][j] != null ) {
144
+ return f[i][j];
145
+ }
146
+ int ans = dfs(i + 1 , j);
147
+ if (j > 0 ) {
148
+ ans = Math . max(ans, prices[i] + dfs(i + 1 , 0 ) - fee);
149
+ } else {
150
+ ans = Math . max(ans, - prices[i] + dfs(i + 1 , 1 ));
151
+ }
152
+ return f[i][j] = ans;
153
+ }
154
+ }
155
+ ```
156
+
157
+ ``` java
158
+ class Solution {
159
+ public int maxProfit (int [] prices , int fee ) {
160
+ int n = prices. length;
161
+ int [][] f = new int [n][2 ];
162
+ f[0 ][1 ] = - prices[0 ];
163
+ for (int i = 1 ; i < n; ++ i) {
164
+ f[i][0 ] = Math . max(f[i - 1 ][0 ], f[i - 1 ][1 ] + prices[i] - fee);
165
+ f[i][1 ] = Math . max(f[i - 1 ][1 ], f[i - 1 ][0 ] - prices[i]);
166
+ }
167
+ return f[n - 1 ][0 ];
168
+ }
169
+ }
170
+ ```
171
+
172
+ ``` java
173
+ class Solution {
174
+ public int maxProfit (int [] prices , int fee ) {
175
+ int f0 = 0 , f1 = - prices[0 ];
90
176
for (int i = 1 ; i < prices. length; ++ i) {
91
- f1 = Math . max(f1, f2 - prices[i]);
92
- f2 = Math . max(f2, f1 + prices[i] - fee);
177
+ int g0 = Math . max(f0, f1 + prices[i] - fee);
178
+ f1 = Math . max(f1, f0 - prices[i]);
179
+ f0 = g0;
93
180
}
94
- return f2 ;
181
+ return f0 ;
95
182
}
96
183
}
97
184
```
@@ -102,12 +189,57 @@ class Solution {
102
189
class Solution {
103
190
public:
104
191
int maxProfit(vector<int >& prices, int fee) {
105
- int f1 = -prices[ 0] , f2 = 0;
192
+ int n = prices.size();
193
+ int f[ n] [ 2 ] ;
194
+ memset(f, -1, sizeof(f));
195
+ function<int(int, int)> dfs = [ &] (int i, int j) {
196
+ if (i >= prices.size()) {
197
+ return 0;
198
+ }
199
+ if (f[ i] [ j ] != -1) {
200
+ return f[ i] [ j ] ;
201
+ }
202
+ int ans = dfs(i + 1, j);
203
+ if (j) {
204
+ ans = max(ans, prices[ i] + dfs(i + 1, 0) - fee);
205
+ } else {
206
+ ans = max(ans, -prices[ i] + dfs(i + 1, 1));
207
+ }
208
+ return f[ i] [ j ] = ans;
209
+ };
210
+ return dfs(0, 0);
211
+ }
212
+ };
213
+ ```
214
+
215
+ ```cpp
216
+ class Solution {
217
+ public:
218
+ int maxProfit(vector<int>& prices, int fee) {
219
+ int n = prices.size();
220
+ int f[n][2];
221
+ memset(f, 0, sizeof(f));
222
+ f[0][1] = -prices[0];
223
+ for (int i = 1; i < n; ++i) {
224
+ f[i][0] = max(f[i - 1][0], f[i - 1][1] + prices[i] - fee);
225
+ f[i][1] = max(f[i - 1][1], f[i - 1][0] - prices[i]);
226
+ }
227
+ return f[n - 1][0];
228
+ }
229
+ };
230
+ ```
231
+
232
+ ``` cpp
233
+ class Solution {
234
+ public:
235
+ int maxProfit(vector<int >& prices, int fee) {
236
+ int f0 = 0, f1 = -prices[ 0] ;
106
237
for (int i = 1; i < prices.size(); ++i) {
107
- f1 = max(f1, f2 - prices[ i] );
108
- f2 = max(f2, f1 + prices[ i] - fee);
238
+ int g0 = max(f0, f1 + prices[ i] - fee);
239
+ f1 = max(f1, f0 - prices[ i] );
240
+ f0 = g0;
109
241
}
110
- return f2 ;
242
+ return f0 ;
111
243
}
112
244
};
113
245
```
@@ -116,12 +248,66 @@ public:
116
248
117
249
```go
118
250
func maxProfit(prices []int, fee int) int {
119
- f1, f2 := -prices[0], 0
120
- for i := 1; i < len(prices); i++ {
121
- f1 = max(f1, f2-prices[i])
122
- f2 = max(f2, f1+prices[i]-fee)
251
+ n := len(prices)
252
+ f := make([][2]int, n)
253
+ for i := range f {
254
+ f[i] = [2]int{-1, -1}
255
+ }
256
+ var dfs func(i, j int) int
257
+ dfs = func(i, j int) int {
258
+ if i >= n {
259
+ return 0
260
+ }
261
+ if f[i][j] != -1 {
262
+ return f[i][j]
263
+ }
264
+ ans := dfs(i+1, j)
265
+ if j > 0 {
266
+ ans = max(ans, prices[i]+dfs(i+1, 0)-fee)
267
+ } else {
268
+ ans = max(ans, -prices[i]+dfs(i+1, 1))
269
+ }
270
+ f[i][j] = ans
271
+ return ans
272
+ }
273
+ return dfs(0, 0)
274
+ }
275
+
276
+ func max(a, b int) int {
277
+ if a > b {
278
+ return a
279
+ }
280
+ return b
281
+ }
282
+ ```
283
+
284
+ ``` go
285
+ func maxProfit (prices []int , fee int ) int {
286
+ n := len (prices)
287
+ f := make ([][2 ]int , n)
288
+ f[0 ][1 ] = -prices[0 ]
289
+ for i := 1 ; i < n; i++ {
290
+ f[i][0 ] = max (f[i-1 ][0 ], f[i-1 ][1 ]+prices[i]-fee)
291
+ f[i][1 ] = max (f[i-1 ][1 ], f[i-1 ][0 ]-prices[i])
292
+ }
293
+ return f[n-1 ][0 ]
294
+ }
295
+
296
+ func max (a , b int ) int {
297
+ if a > b {
298
+ return a
299
+ }
300
+ return b
301
+ }
302
+ ```
303
+
304
+ ``` go
305
+ func maxProfit (prices []int , fee int ) int {
306
+ f0 , f1 := 0 , -prices[0 ]
307
+ for _ , x := range prices[1 :] {
308
+ f0, f1 = max (f0, f1+x-fee), max (f1, f0-x)
123
309
}
124
- return f2
310
+ return f0
125
311
}
126
312
127
313
func max (a , b int ) int {
@@ -132,6 +318,55 @@ func max(a, b int) int {
132
318
}
133
319
```
134
320
321
+ ### ** TypeScript**
322
+
323
+ ``` ts
324
+ function maxProfit(prices : number [], fee : number ): number {
325
+ const n = prices .length ;
326
+ const f: number [][] = Array .from ({ length: n }, () => [- 1 , - 1 ]);
327
+ const dfs = (i : number , j : number ): number => {
328
+ if (i >= n ) {
329
+ return 0 ;
330
+ }
331
+ if (f [i ][j ] !== - 1 ) {
332
+ return f [i ][j ];
333
+ }
334
+ let ans = dfs (i + 1 , j );
335
+ if (j ) {
336
+ ans = Math .max (ans , prices [i ] + dfs (i + 1 , 0 ) - fee );
337
+ } else {
338
+ ans = Math .max (ans , - prices [i ] + dfs (i + 1 , 1 ));
339
+ }
340
+ return (f [i ][j ] = ans );
341
+ };
342
+ return dfs (0 , 0 );
343
+ }
344
+ ```
345
+
346
+ ``` ts
347
+ function maxProfit(prices : number [], fee : number ): number {
348
+ const n = prices .length ;
349
+ const f: number [][] = Array .from ({ length: n }, () => [0 , 0 ]);
350
+ f [0 ][1 ] = - prices [0 ];
351
+ for (let i = 1 ; i < n ; ++ i ) {
352
+ f [i ][0 ] = Math .max (f [i - 1 ][0 ], f [i - 1 ][1 ] + prices [i ] - fee );
353
+ f [i ][1 ] = Math .max (f [i - 1 ][1 ], f [i - 1 ][0 ] - prices [i ]);
354
+ }
355
+ return f [n - 1 ][0 ];
356
+ }
357
+ ```
358
+
359
+ ``` ts
360
+ function maxProfit(prices : number [], fee : number ): number {
361
+ const n = prices .length ;
362
+ let [f0, f1] = [0 , - prices [0 ]];
363
+ for (const x of prices .slice (1 )) {
364
+ [f0 , f1 ] = [Math .max (f0 , f1 + x - fee ), Math .max (f1 , f0 - x )];
365
+ }
366
+ return f0 ;
367
+ }
368
+ ```
369
+
135
370
### ** ...**
136
371
137
372
```
0 commit comments