714. Best Time to Buy and Sell Stock with Transaction Fee(M)

题目描述

给定一个整数数组 prices 表示股票的价格,第 i 个元素表示第 i 天的股票价格,同时给定 fee 表示进行一次股票交易需要承担的费用。
允许进行多次股票交易,但每次交易都需要承担 fee 的费用。并且你在某一时刻只允许拥有一支股票。
要求返回能获得的最大利益。原题以及例子如下,
这里写图片描述

关于这种选择类的问题,最容易想到的便是枚举出所有的可能,然后选出最大的利益,要实现这种方法可以使用二叉树的方法,因为每个结点能做出两种选择,买或者卖,代表着二叉树的两个分支,用二叉树能很容易的枚举出所有可能,但显然用这种方法的代价过于高昂,但这不失为提供思路的好方法。这里我们考虑如何减少树每层结点的个数,从而优化算法的时间复杂度。
首先我们考虑整个购买股票的流程,每一次购买股票,代表新的一次交易开始,那么此时购买股票的profit要大于我上次购买股票时的profit,才会选择购买新的股票,即上一组买卖股票的结束(这里不用担心如果上一次股票未卖出时便再次购买股票,因为如果在上一次股票还未卖出的情况下,这一次购买股票得到的profit一定是小于上一次的,如果不理解可以自己用下面的公式试试)。同理当这次出售股票获取的profit大于上一次时,才卖出股票。下面我用pre-Buy和buy分别表示上一次购买和这一次购买时获得的profit,pre-Sell和sell分别代表上一次出售股票和这次出售股票获得的profit。这里要注意到一个细节,我计算pre-Sell时,是用pre-Buy+currentPrice,这意味着,如果在未买入新股票的情况下,会持续比较是否在其他时刻出售股票,使得buy大于pre-Buy。在这种情况下,我们就不用考虑每一层所有结点的情况,每一层只用考虑1个结点,即时间复杂度为O(n)。

sell = pre-Buy + currentPirce;
buy = pre-Sell - currentPrice - fee;
pre-Sell = Max(pre-Sell, sell);
pre-Buy = Max(pre-Buy, buy);

如果还是不理解,建议多举几个例子,代入试试。
下面是源代码,

class Solution {
 public:
  int maxProfit(vector<int>& prices, int fee) {
    int buy = INT_MIN, sell = 0;
    for (int price : prices) {
      int tmp = sell;
      sell = max(sell, buy + price);
      buy = max(buy, tmp - price - fee);
    }
    return sell;
  }
};

另外这里还有另外一种比较繁琐的写法,如果不理解上一种写法,可以看看这种,源码如下,

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int l = prices.size();
        if (l == 0) return 0;
        int maxx = prices[l - 1];
        int minn = prices[l - 1];
        int sum = 0;
        bool isUsed = false;
        for (int i = l - 2; i >= 0; --i) {
            if (prices[i] > minn + fee || prices[i] > maxx) {
                if (maxx - minn - fee > 0) {
                    sum += maxx - minn - fee;
                    isUsed = true;
                }
                maxx = prices[i];
                minn = prices[i];
                isUsed = false;
            } else {
                minn = min(minn, prices[i]);
            }
        }
        if (!isUsed && maxx - minn - fee > 0) {
            sum += maxx - minn - fee;
        }
        return sum;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值