题目描述

✅ 714. 买卖股票的最佳时机含手续费

image-20260929000037116

image-20260929000037117

题意分析

可以进行多笔交易,但买入下一股之前必须先卖掉手中的股票。每次完整买卖只扣一次手续费,目标是最大化最终收益。手续费会让频繁交易付出额外成本,需要同时考虑继续持有和立即卖出的选择。

解法:持有/不持有状态 DP

核心思路

[!blue]

按当天结束时是否持股定义两个状态:cash 是不持股时的最大累计现金,hold 是持有一股时的最大累计现金,已经扣除这股股票的买入成本。hold 包含以前交易留下的收益,因此也可能为正。

设今天价格为 price,两个状态都从昨天的值转移:

  • 今天不持股:昨天已经不持股且今天不操作,或者昨天持股、今天卖出。对应 cash = max(旧 cash, 旧 hold + price - fee)。
  • 今天持股:昨天已持股且继续持有,或者昨天不持股、今天买入。对应 hold = max(旧 hold, 旧 cash - price)。

每种日末状态的合法来源都已列出;到达同一状态后,未来可执行的操作相同,所以只需保留累计现金最大的方案。手续费统一放在卖出转移中扣除,保证每笔交易只收费一次。

第一天不操作得到 cash = 0,买入得到 hold = -prices[0]。遍历结束返回 cash,对应已经完成交易的收益。始终不交易的方案会一直保留,所以所有交易都无法获利或只有一天时,答案就是 $0$。

解题步骤

  1. 令 cash = 0、hold = -prices[0],从第二天开始遍历价格。
  2. 将昨天的 cash 保存到 preCash。
  3. 用原来的 hold 计算今天的 cash,比较不操作与卖出后的收益。
  4. 用 preCash 计算今天的 hold,比较继续持有与买入后的现金。
  5. 扫描结束返回 cash。

代码实现

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int cash = 0;
        int hold = -prices[0];

        for (int i = 1; i < prices.length; i++) {
            // 保存昨天现金,使两个转移都使用上一天状态
            int preCash = cash;

            // cash 表示不持股,hold 表示持股,手续费在卖出时扣除。
            cash = Math.max(cash, hold + prices[i] - fee);
            hold = Math.max(hold, preCash - prices[i]);
        }

        return cash;
    }
}
func maxProfit(prices []int, fee int) int {
    cash := 0
    hold := -prices[0]
    for i := 1; i < len(prices); i++ {
        // 保存昨天现金,使两个转移都使用上一天状态
        preCash := cash

        // cash 表示不持股,hold 表示持股,手续费在卖出时扣除。
        if hold+prices[i]-fee > cash {
            cash = hold + prices[i] - fee
        }
        if preCash-prices[i] > hold {
            hold = preCash - prices[i]
        }
    }
    return cash
}

复杂度分析

  • 时间复杂度:$O(n)$,每天处理两个状态。
  • 空间复杂度:$O(1)$,仅保存滚动状态与旧值。

关键点总结

[!green]

  • 手续费只扣一次,买卖两侧不能重复扣。
  • preCash 保存昨天的空仓收益,让两条转移读取同一天的旧状态。

易错点总结

[!yellow]

  • 持仓初值零相当于免费获得一股。
  • 买入只用负价格而不继承历史现金,会退化为最多一笔交易。
  • 手续费过高时仍强行交易,忽略了保持零收益的选择。

相似题目

题目 难度 关联与区别
122. 买卖股票的最佳时机 II 中等 加入手续费后不能把每个正差都当作独立收益,需维护持有与空仓最优状态。
309. 买卖股票的最佳时机含冷冻期 中等 同样在基础股票DP中增加交易限制,原题增加冷冻期,本题每笔交易扣费用。
121. 买卖股票的最佳时机 简单 以持有状态和交易次数描述每天的最优收益;本题在交易转移时计入手续费,该题只允许一次买卖。
123. 买卖股票的最佳时机 III 困难 以持有状态和交易次数描述每天的最优收益;本题在交易转移时计入手续费,该题最多完成两笔交易。
188. 买卖股票的最佳时机 IV 困难 以持有状态和交易次数描述每天的最优收益;本题在交易转移时计入手续费,该题推广到 k 笔交易。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/41461234
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!