Skip to content

Commit 825a125

Browse files
authored
feat: add solutions to lc problem: No.0714 (#1746)
No.0714.Best Time to Buy and Sell Stock with Transaction Fee
1 parent 9f04133 commit 825a125

File tree

7 files changed

+569
-75
lines changed

7 files changed

+569
-75
lines changed

solution/0700-0799/0714.Best Time to Buy and Sell Stock with Transaction Fee/README.md

+261-26
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,31 @@
4949

5050
<!-- 这里可写通用的实现逻辑 -->
5151

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

54-
设 f1 表示当天持有股票的最大利润,f2 表示当天没持有股票的最大利润
54+
我们设计一个函数 $dfs(i, j)$,表示从第 $i$ 天开始,状态为 $j$ 时,能够获得的最大利润。其中 $j$ 的取值为 $0, 1$,分别表示当前不持有股票和持有股票。答案即为 $dfs(0, 0)$
5555

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

58-
从第 2 天开始,当天结束时:
58+
如果 $i \geq n$,那么没有股票可以交易了,此时返回 $0$;
5959

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)$ 的返回值。
6261

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)$。
6477

6578
<!-- tabs:start -->
6679

@@ -71,12 +84,39 @@
7184
```python
7285
class Solution:
7386
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
80120
```
81121

82122
### **Java**
@@ -85,13 +125,60 @@ class Solution:
85125

86126
```java
87127
class Solution {
128+
private Integer[][] f;
129+
private int[] prices;
130+
private int fee;
131+
88132
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];
90176
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;
93180
}
94-
return f2;
181+
return f0;
95182
}
96183
}
97184
```
@@ -102,12 +189,57 @@ class Solution {
102189
class Solution {
103190
public:
104191
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];
106237
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;
109241
}
110-
return f2;
242+
return f0;
111243
}
112244
};
113245
```
@@ -116,12 +248,66 @@ public:
116248
117249
```go
118250
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)
123309
}
124-
return f2
310+
return f0
125311
}
126312

127313
func max(a, b int) int {
@@ -132,6 +318,55 @@ func max(a, b int) int {
132318
}
133319
```
134320

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+
135370
### **...**
136371

137372
```

0 commit comments

Comments
 (0)