每日一题:买卖股票的最佳时机III

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
     随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。   
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。   
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:

输入:prices = [7,6,4,3,1] 
输出:0 
解释:在这个情况下, 没有交易完成, 所以最大利润为 0。

示例 4:

输入:prices = [1]
输出:0

提示:

  • 1 <= prices.length <= 10^5
  • 0 <= prices[i] <= 10^5

买卖股票系列的第三题。

先来看分类讨论。

题目限制了只能交易两次。那么在第 i 天,我只有以下几种操作方式:

  • 进行第一次买入。(buy1)
  • 进行第一次卖出,前提是已经买入。(sell1)
  • 进行第二次买入,前提是已经进行第一次卖出。(buy2)
  • 进行第二次卖出,前提是进行第二次买入。(sell2)
  • 什么都不做。

再来看各个操作对达成最大利润的贡献:

  • 进行第一次买入:-price[ i ]。没赚钱还花出了当前价格。
  • 进行第一次卖出:赚了price[ i ] + buy1。赚了当前价格减去买入时花的钱。
  • 进行第二次买入:赚了sell1 - price[ i ]。赚了第一次赚得钱减去这次花的钱。
  • 进行第二次卖出:赚了price[ i ] + buy2。赚了第一次赚得钱和这次赚得钱。
  • 什么都不做:无影响,对结果的贡献为0。

那么可以看到,这几种操作的结果是层层递进依赖的,也就是可以通过sell1计算出第i日第一次卖出的利润结果,利用buy2计算出第i日第二次买入的利润结果......

用公式表示如下:

buy1 = -price[i];

sell1 = price[i] + buy1;

buy2 = sell1 - price[i];

sell2 = price[i] + buy2;

这样就可以通过遍历每一天,记录过程中的最大值,目标最大利润将保存在sell2中。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int buy1 = -prices[0];
        int buy2 = -prices[0];
        int sell1 = 0;
        int sell2 = 0;
        for(int i = 1;i < prices.size();++i){
            buy1 = max(buy1,-prices[i]);
            sell1 = max(sell1,prices[i] + buy1);
            buy2 = max(buy2,sell1 - prices[i]);
            sell2 = max(sell2,buy2 + prices[i]);
        }
        return sell2;
    }
};

这里初始值为什么是这样?

buy1很好理解,第0天就是prices[0]。

而buy2相当于在第0天,我已经买入了1次,又卖出了1次,又买入了。

sell1就相当于第0天买了又卖。

sell2相当于第0天买了卖,又买了卖。

到这里分类讨论法就结束了。

但是如果我允许买卖3次、100次、k次呢?是否有一个通用的方法?

动态规划

也就是买卖股票的最佳时机IV这道题了。

每日一题:买卖股票的最佳时机IV-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值