1.题目链接:
给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费 用。
你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
返回获得利润的最大值。
注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
示例 1:
输入:prices = [1, 3, 2, 8, 4, 9], fee = 2
输出:8
解释:
能够达到的最大利润:
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8
示例 2:
输入:prices = [1,3,7,5,10,3], fee = 3
输出:6
3. 解法(动态规划):
算法思路:
1. 状态表示:
对于线性 dp ,我们可以用「经验 + 题目要求」来定义状态表示:
| i. | 以某个位置为结尾,巴拉巴拉; |
ii. 以某个位置为起点,巴拉巴拉。
这里我们选择比较常用的方式,以某个位置为结尾,结合题目要求,定义一个状态表示:由于有「买入」「可交易」两个状态,因此我们可以选择用两个数组,其中:
| f[i] 表示:第 i 天结束后,处于「买入」状态,此时的最大利润;g[i] 表示:第 i 天结束后,处于「卖出」状态,此时的最大利润。 | |
| ▪ | |
| ▪ | |
2. 状态转移方程:
我们选择在「卖出」的时候,支付这个手续费,那么在「买入」的时候,就不用再考虑手续费的问题。
| 对于 f[i] ,我们有两种情况能到达这个状态: | ||
| ◦ | ||
| i. | 在 i - 1 天「持有」股票,第 i 天啥也不干。此时最大收益为 f[i - 1] ; | |
ii. 在 i - 1 天的时候「没有」股票,在第 i 天买入股票。此时最大收益为 g[i - 1] - prices[i]) ;
两种情况下应该取最大值,因此 f[i] = max(f[i - 1], g[i - 1] -
prices[i]) 。
| 对于 g[i] ,我们也有两种情况能够到达这个状态: | ||
| ◦ | ||
| i. | 在 i - 1 天「持有」股票,但是在第 i 天将股票卖出。此时最大收益为:f[i - 1] | |
+ prices[i] - fee) ,记得手续费;
ii. 在 i - 1 天「没有」股票,然后第 i 天啥也不干。此时最大收益为:g[i - 1] ;
两种情况下应该取最大值,因此 g[i] = max(g[i - 1], f[i - 1] + prices[i]
- fee) 。
3. 初始化:
由于需要用到前面的状态,因此需要初始化第一个位置。
| 对于 f[0] ,此时处于「买入」状态,因此 f[0] = -prices[0] ; | |
| ◦ | |
| ◦ | |
4. 填表顺序:
毫无疑问是「从左往右」,但是两个表需要一起填。
5. 返回值:
应该返回「卖出」状态下,最后一天的最大值收益:g[n - 1] 。
Java算法代码:
class Solution {
public int maxProfit(int[] prices, int fee) {
// 1.创建dp表
// 2.初始化
// 3.填表
// 4.返回值
int n = prices.length;
int[] f = new int[n];
int[] g = new int[n];
f[0] = - prices[0];
for(int i = 1; i < n; i++) {
f[i] = Math.max(f[i - 1],g[i - 1] - prices[i]);
g[i] = Math.max(g[i - 1],f[i - 1] + prices[i] - fee);
}
return g[n - 1];
}
}
运行结果:

贪心策略:

&spm=1001.2101.3001.5002&articleId=148367770&d=1&t=3&u=f83b84c35dd84fd5b280a32c1c95e4ab)
1283

被折叠的 条评论
为什么被折叠?



