代码随想录算法训练营第五十一天 | 309.买卖股票的最佳时机含冷冻期(需要复习)、714.买卖股票的最佳时机含手续费

文章目录

  • 一、309.买卖股票的最佳时机含冷冻期
  • 二、714.买卖股票的最佳时机含手续费


一、309.买卖股票的最佳时机含冷冻期

题目链接

本题卡哥分成的四种状态感觉理解起来稍稍混乱,官方题解中的三种状态更容易理解一些。

当前股票有两种状态:买入和卖出,其中卖出又分为冷冻期和非冷冻期。定义三种状态:

  dp[i][0]:持有股票的最大收益
  dp[i][1]:不持有股票,且处于冷冻期中的最大收益
  dp[i][2]:不持有股票,且不处于冷冻期中的最大收益

初始化:
第0天持有股票,只能是当天买入,对应负收益-prices[i];
第0天不持有股票且处于冷冻期,不存在这种情况,为递推公式将dp[i][1]置为0;
第0天不持有股票且不处于冷冻期,就是没买,对应收益为0。

dp[0][0] = -prices[0];
dp[0][1] = 0;
dp[0][2] = 0;

递推公式:
第i天持有股票的最大收益等于:第i-1天就已经持有的;或在第i天买入的,那么第i-1天的状态为不持有股票且不处于冷冻期;

dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i]); 

第i天不持有且冷冻,说明第i-1天持有股票并刚执行完卖出,收益为第i-1天持有股票的最大收益+第i天卖出股票的正收益prices[i];

dp[i][1] = dp[i - 1][0] + prices[i]; 

第i天不持有且不冷冻,说明在第i-1天没有进行任何操作,第i-1天没有任何操作对应非冷冻期dp[i - 1][2]或冷冻期dp[i - 1][1]
(前一天就是冷冻期或者更早就是冷冻期)

dp[i][2] = max(dp[i - 1][1], dp[i - 1][2]); 

整体代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.size() == 0) return 0;
        int len = prices.size();
        
        vector<vector<int>> dp(prices.size(), vector(3, 0));
        dp[0][0] = -prices[0]; 
        for (int i = 1; i < prices.size(); i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i]); 
            dp[i][1] = dp[i - 1][0] + prices[i]; 
            dp[i][2] = max(dp[i - 1][1], dp[i - 1][2]); 
        }
        return max(dp[len - 1][1], dp[len - 1][2]); // 最后一天(len-1天)持有股票的收益一定不如不持有股票
    }
};

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

题目链接

本题和买卖股票的最佳时机II的唯二区别在于:
1、不持有股票的状态dp[i][1]在取最大值中,在第i天当天卖出股票的收益需要减去手续费。
2、最后取结果时要去不持有和持有的最大值,因为有扣手续费的条件,不持有股票不一定比持有股票收益高。

代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int len = prices.size();
        if (len == 0) return 0;
        vector<vector<int>> dp(len, vector<int>(2)); // 0持有,1不持有
        dp[0][0] = -prices[0]; // 买入不用手续费
        for (int i = 1; i < len; i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee); // 与II的区别在这里-fee
        }
        return max(dp[len - 1][0], dp[len - 1][1]); // 手续费的存在要比较持有和不持有的收益谁大
    }
};

你可能感兴趣的:(算法)