Skip to content

Commit 9117cf1

Browse files
author
lucifer
committed
feat: $714
1 parent 17b5429 commit 9117cf1

File tree

3 files changed

+183
-5
lines changed

3 files changed

+183
-5
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,12 +294,13 @@ leetcode 题解,记录自己的 leetcode 解题之路。
294294
- [0560. 和为 K 的子数组](./problems/560.subarray-sum-equals-k.md)
295295
- [0609. 在系统中查找重复文件](./problems/609.find-duplicate-file-in-system.md)
296296
- [0611. 有效三角形的个数](./problems/611.valid-triangle-number.md)
297-
- [0673. 最长递增子序列的个数](./problems/673.number-of-longest-increasing-subsequence.md) 🆕
298-
- [0686. 重复叠加字符串匹配](./problems/686.repeated-string-match.md) 🆕
297+
- [0673. 最长递增子序列的个数](./problems/673.number-of-longest-increasing-subsequence.md)
298+
- [0686. 重复叠加字符串匹配](./problems/686.repeated-string-match.md)
299299
- [0718. 最长重复子数组](./problems/718.maximum-length-of-repeated-subarray.md)
300+
- [0714. 买卖股票的最佳时机含手续费](./problems/714.best-time-to-buy-and-sell-stock-with-transaction-fee.md) 🆕
300301
- [0754. 到达终点数字](./problems/754.reach-a-number.md)
301302
- [0785. 判断二分图](./problems/785.is-graph-bipartite.md)
302-
- [0790. 多米诺和托米诺平铺](./problems/790.domino-and-tromino-tiling.md) 🆕
303+
- [0790. 多米诺和托米诺平铺](./problems/790.domino-and-tromino-tiling.md)
303304
- [0799. 香槟塔](./problems/799.champagne-tower.md) 🆕
304305
- [0801. 使序列递增的最小交换次数](./problems/801.minimum-swaps-to-make-sequences-increasing.md) 🆕
305306
- [0816. 模糊坐标](./problems/816.ambiguous-coordinates.md)

SUMMARY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,9 @@
184184
- [0560. 和为 K 的子数组](./problems/560.subarray-sum-equals-k.md)
185185
- [0609. 在系统中查找重复文件](./problems/609.find-duplicate-file-in-system.md)
186186
- [0611. 有效三角形的个数](./problems/611.valid-triangle-number.md)
187-
- [0673. 最长递增子序列的个数](./problems/673.number-of-longest-increasing-subsequence.md) 🆕
188-
- [0686. 重复叠加字符串匹配](./problems/686.repeated-string-match.md) 🆕
187+
- [0673. 最长递增子序列的个数](./problems/673.number-of-longest-increasing-subsequence.md)
188+
- [0686. 重复叠加字符串匹配](./problems/686.repeated-string-match.md)
189+
- [0714. 买卖股票的最佳时机含手续费](./problems/714.best-time-to-buy-and-sell-stock-with-transaction-fee.md) 🆕
189190
- [0718. 最长重复子数组](./problems/718.maximum-length-of-repeated-subarray.md)
190191
- [0754. 到达终点数字](./problems/754.reach-a-number.md)
191192
- [0785. 判断二分图](./problems/785.is-graph-bipartite.md)
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
## 题目地址(714. 买卖股票的最佳时机含手续费)
2+
3+
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
4+
5+
## 题目描述
6+
7+
```
8+
给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。
9+
10+
你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
11+
12+
返回获得利润的最大值。
13+
14+
注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
15+
16+
示例 1:
17+
18+
输入: prices = [1, 3, 2, 8, 4, 9], fee = 2
19+
输出: 8
20+
解释: 能够达到的最大利润:
21+
在此处买入 prices[0] = 1
22+
在此处卖出 prices[3] = 8
23+
在此处买入 prices[4] = 4
24+
在此处卖出 prices[5] = 9
25+
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
26+
27+
注意:
28+
29+
0 < prices.length <= 50000.
30+
0 < prices[i] < 50000.
31+
0 <= fee < 50000.
32+
```
33+
34+
## 前置知识
35+
36+
- 动态规划
37+
38+
## 公司
39+
40+
- 暂无
41+
42+
## 记忆化递归
43+
44+
### 思路
45+
46+
首先明确一点。 如果没有交易费用,那么和另一道力扣的简单难度题目一样。 多了交易费用导致问题稍微复杂了一点。加了交易费用有什么不同呢?
47+
48+
举一个例子大家就明白了。 比如 prices = [1,1,2,2,6] fee = 3。 如果没有按照无交易费的原则**只要有利可图就交易**,那么我们的收益为 1。实际上,在 1 买入, 6 卖出却可以得到 3 的收益。其根本原因在于**交易次数对结果是有影响的**
49+
50+
这道题不能使用上述的贪心策略,而必须使用动态规划。
51+
52+
> 动态规划和贪心有着很强的关联性。
53+
54+
定义 dp[i] 为到第 i 天(0=< i <n)为止的收益,那么答案就是 dp[n-1]。但是由于题目限定了只能**在手上没有股票的时候才能买,手上有股票的时候才能卖(这很显然)**。因此我们需要多定义一个维度的状态,表示现在手上是否有股票。标识是否手上有股票只需要一个长度为 2 的列表就可以了。
55+
56+
因此我们可以使用 dp[i][0] 表示没有股票的情况下的最大利润,dp[i][1] 表示有股票的情况下的最大利润。
57+
58+
那么:
59+
60+
- 如果第 i 天手上没有股票,要么是 i - 1 没股票,今天什么都不做。要么是 i - 1 手上有股票,今天卖了它。因此 dp[i][0] 就是这两种情况的利润最大值。
61+
62+
- 如果第 i 天手上有股票,要么是 i - 1 有股票,今天什么都不做。要么是 i - 1 手上没有股票,今天买了它。因此 dp[i][0] 就是这两种情况的利润最大值。
63+
64+
最后返回 dp[n-1][0] 即可。
65+
66+
> 由于 dp[n-1][1] <= dp[n-1][0] ,因此直接返回 dp[n-1][0] 即可。
67+
68+
base case 见下方代码的递归出口。
69+
70+
### 关键点
71+
72+
- 记忆化递归
73+
74+
### 代码
75+
76+
- 语言支持:Python3
77+
78+
Python3 Code:
79+
80+
```python
81+
82+
class Solution:
83+
def maxProfit(self, prices: List[int], fee: int) -> int:
84+
def dp(i):
85+
if i == 0:
86+
return 0, -prices[0] - fee
87+
sell, buy = dp(i - 1)
88+
return max(sell, buy + prices[i]), max(buy, sell - prices[i] - fee)
89+
90+
return dp(len(prices) - 1)[0]
91+
92+
```
93+
94+
**复杂度分析**
95+
96+
令 n 为数组长度。
97+
98+
- 时间复杂度:$O(n)$
99+
- 空间复杂度:$O(n)$
100+
101+
## DP
102+
103+
### 思路
104+
105+
使用 dp 的思路和上面一样,只是代码形式不同而已。
106+
107+
### 关键点
108+
109+
- 滚动数组优化技巧
110+
111+
### 代码
112+
113+
- 语言支持:Python3
114+
115+
Python3 Code:
116+
117+
```py
118+
119+
class Solution:
120+
def maxProfit(self, prices: List[int], fee: int) -> int:
121+
n = len(prices)
122+
dp = [[0 for i in range(2)]] * n
123+
for i in range(n):
124+
if i == 0:
125+
dp[i][0] = 0
126+
dp[i][1] = -1 * prices[i]
127+
else:
128+
dp[i][0] = max(dp[i - 1][1] + prices[i] - fee, dp[i - 1][0])
129+
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
130+
131+
return dp[-1][0]
132+
133+
```
134+
135+
**复杂度分析**
136+
137+
令 n 为数组长度。
138+
139+
- 时间复杂度:$O(n)$
140+
- 空间复杂度:$O(n)$
141+
142+
使用 DP 数组的好处就是可以使用滚动数组优化。比如这道题使用滚动数组可将空间进一步压缩。
143+
144+
```py
145+
class Solution:
146+
def maxProfit(self, prices: List[int], fee: int) -> int:
147+
n = len(prices)
148+
# [手里没股票, 手里有股票]
149+
dp = [0, 0]
150+
for i in range(n):
151+
if i == 0:
152+
dp[0] = 0
153+
dp[1] = -1 * prices[i] - fee
154+
else:
155+
dp[0] = max(dp[0], dp[1] + prices[i])
156+
dp[1] = max(dp[1], dp[0] - prices[i] - fee)
157+
158+
return dp[0]
159+
```
160+
161+
**复杂度分析**
162+
163+
令 n 为数组长度。
164+
165+
- 时间复杂度:$O(n)$
166+
- 空间复杂度:$O(1)$
167+
168+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
169+
170+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
171+
172+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
173+
174+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
175+
176+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 commit comments

Comments
 (0)