代码随想录Day53

今天继续学习动规解决相关问题。

123.买卖股票的最佳时机|||

给定一个数组,它的第 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 。

思路:

1.Day52的|和||分别对应两种极端情况,一种是只能买卖一次,一种是能买卖无数次。而本题相当于是折中选了一种普通情况,难度一下子就又升高了一点。但实际上具体分析后发现本题套路还是和前面类似,不过本题中我们要拆分的状态更多了,因为得统计第一次持有和不持有以及第二次持有和不持有。

2.因此,dp数组含义为dp[i][0]表示第i天不操作,dp[i][1]和dp[i][2]分别表示第一次持有和第一次不持有的最大金额,dp[i][3]和dp[i][4]分别表示第二次持有和第二次不持有的最大金额。

3.关于递推公式这一块,牢记持有与不持有的推导:持有要么代表当天买入(前一天不持有状态减去当天股票价值),要么代表之前就已经持有(延续前一天的持有状态);不持有要么代表当天卖出(前一天持有股票状态加上当天股票价值),要么代表之前已经不持有(延续前一天的不持有状态。)

class Solution {
public:
    int maxProfit(vector& prices) {
        vector> dp(prices.size(), vector(5));

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

        for(int i = 1; i < prices.size(); i++){
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
            dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2]);
            dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
            dp[i][4] = max(dp[i - 1][3] + prices[i], dp[i - 1][4]);
        }

        return dp[prices.size() - 1][4];
    }
};

启发:

1.本题实际上可以把dp[i][0]的状态给优化掉,因为没有操作的情况下现金实际上就是0。还有实际上本题只需要存储第i天和i-1天的状态,因此理论上来说可以用滚动数组进行空间复杂度的优化。

2.本题在最后返回值时可能会选择取最大值返回,但实际上dp[i][4]作为第二次不持有股票的情况,其一定是包含了dp[i][2]的情况的,因此直接返回dp[i][4]即可。

你可能感兴趣的:(代码随想录,算法,leetcode,动态规划,数据结构,c++)