leetcode刷题详解——买卖股票的最佳时机含手续费

1. 题目链接:714. 买卖股票的最佳时机含手续费

2. 题目描述:

给定一个整数数组 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

提示:

  • 1 <= prices.length <= 5 * 104
  • 1 <= prices[i] < 5 * 104
  • 0 <= fee < 5 * 104

3. 解法(动态规划):

3.1 算法思路:

1. 状态表示:

由于买入可交易两个状态,因此我们可以选择用两个数组,其中:

f[i]表示:第i天结束后,处于买入状态,此时的最大利润

g[i]表示:第i天结束后,处于卖出状态,此时的最大利润
请添加图片描述

2. 状态转移方程:

我们选择在卖出的时候,支付这个手续费,那么在买入的时候,就不用再考虑手续费的问题

对于f[i],我们有两种情况能到达这个状态:

  1. 对于 f[i],我们两种情况能到达这个状态:
    1. i-1天持有股票,第 i天啥也不干,此时最大收益为 f[i-1]
    2. i-1天的时候没有股票,在第i天买入股票,此时最大收益为 g[i-1]-prices[i]
    3. 两种情况哎应该取最大值,因此 f[i]=max(f[i-1],g[i-1]-prices[i])
  2. 对于 g[i],我们也有两种情况能够到达这个状态:
    1. i-1天持有股票,但是在第i天将股票卖出,此时最大收益为 f[i-1]+prices[i]-fee),记得手续费
    2. i-1天没有股票,然后第i天啥也不干,此时最大收益为:g[i-1]
    3. 两种情况下应该取最大值,因此 g[i]=max(g[i-1],f[i-1]+prices[i]-fee)
      请添加图片描述
3. 初始化:

由于需要用到前面的状态,因此需要初始化第一个位置

  1. 对于 f[0],此时处于买入状态,因此 f[0]=-prices[0]

  2. 对于 g[0],此时处于没有股票状态,啥也不干即可获得最大收益,因此 g[0]=0

4. 填表顺序:

从左往右,两个表需要一起填

5. 返回值:

应该返回卖出状态下,最后一天的最大收益:g[n-1]

3.2 C++算法代码:

class Solution {
public:
    // 计算最大利润
    int maxProfit(vector<int>& prices, int fee) {
        int n = prices.size(); // 获取价格数组的长度
        vector<int> f(n); // 定义一个长度为n的数组f,用于存储第i天结束时的最大利润
        auto g = f; // 将数组f的引用赋值给g,方便后续操作
        f[0] = -prices[0]; // 初始化第一天的利润为-prices[0]
        for (int i = 1; i < n; i++) {
            // 更新第i天结束时的最大利润,取前一天的最大利润和前一天卖出股票后的最大利润之和与当前价格的差值的最大值
            f[i] = max(f[i - 1], g[i - 1] - prices[i]);
            // 更新第i天结束时的最大利润,取前一天的最大利润和前一天买入股票后的最大利润之和与当前价格减去手续费的最大值
            g[i] = max(g[i - 1], f[i - 1] + prices[i] - fee);
        }
        return g[n - 1]; // 返回最后一天结束时的最大利润
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值