"给血雨腥风的二级市场留下八个大字——巴菲特就那么回事"
题目链接: 714. 买卖股票的最佳时机含手续费,给定一个整数数组 prices,其中 prices[i] 表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。返回获得利润的最大值。注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
输入:
输出:
解释: 能够达到的最大利润: 在此处买入 ;在此处卖出 ;在此处买入 ;在此处卖出
总利润:
本题 # 122. 买卖股票的最佳时机2 仅差了手续费这一条件。每次交易(一买一卖为一次交易)就会有一笔手续费,故我们固定买卖股票是后收费,即买入时没有手续费,卖出股票时才会出现手续费。
中规中矩的动态规划
1、确定 dp 数组以及其含义
由于不能同时参与多笔交易,即必须卖出手中股票才能再次购买,亦或手中不持股时才能买入,因此每天交易结束后仅有两种情况,即,1、手中持股,2、手中不持股。
故,用动态规划数组 表示第 日持股状态为 时,我们手上最大的收益,其中,
-
-
或者 ,持股 (),指不持股 ()
2、确定 dp 对应的状态方程
如第 天持股,即 ,存在两种可能:
👉 第 天也持股:
👉 第 天不持股并在第 天买入(此时无手续费):
故,
如第 天不持股,即 ,存在两种可能:
👉第 天也不持股:
👉第 天卖出(此时有手续费):
故,
3、确定 dp 的初始状态
第 日持股与不持股的最大收益为:
4、确定遍历顺序
从第 天一直遍历到第 天
5、确定最终返回值
最后一日肯定不能再持有股票了,如果持有股票,利润肯定不是最大的,故选择最后一日不持股的状态,即,。
6、代码示例
/**
* 空间复杂度 O(n),n是prices数组的长度
* 时间复杂度 O(n)
*/
function maxProfit(prices: number[], fee: number): number {
const len = prices.length;
const dp = Array.from({ length: len }, () => [0, 0]);
dp[0][0] = -prices[0];
for(let i = 1; i < len; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
}
return dp[len - 1][1];
};
状态压缩
/**
* 空间复杂度 O(1)
* 时间复杂度 O(n)
*/
function maxProfit(prices: number[], fee: number): number {
const len = prices.length;
let dp0 = -prices[0];
let dp1 = 0
for(let i = 1; i < len; i++) {
[ dp0, dp1 ] = [
Math.max(dp0, dp1 - prices[i]),
Math.max(dp1, dp0 + prices[i] - fee),
];
}
return dp1;
};
参考
至此 动规团灭股票买卖 就全部更新完毕啦...