代码随想录算法训练营第五十天|LeetCode123. 买卖股票的最佳时机 III、LeetCode188. 买卖股票的最佳时机 IV

一、LeetCode123. 买卖股票的最佳时机 III

题目链接:123. 买卖股票的最佳时机 III

因为股票至多能买卖两次,所以每一天的股票我们可以有五个状态:不处理、第一次买卖、第二次买卖。
即:dp[i][0]表示第i天股票不做处理时的状态。
dp[i][1]表示第i天保持第一次买入时的状态。
dp[i][2]表示第i天保持第一次卖出时的状态。
dp[i][3]表示第i天保持第二次买入时的状态。
dp[i][4]表示第i天保持第二次卖出时的状态。

1、dp数组及下标含义:dp[i][j] 表示第i天股票买卖为j时手里现金的最大值。
2、递推公式:
(1)股票不做任何处理时当天的金额就是前一天金额,dp[i][0] = dp[i - 1][0];
(2)第i天保持第一次买入时,dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1]);
(3)第i天保持第一次卖出时,dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2]);
(4)第i天保持第二次买入时,dp[i][3] =max(dp[i - 1][2] - prices[i], dp[i - 1][3]);
(5)第i天保持第二次卖出时,dp[i][4] = max(dp[i - 1[3] + prices[i], dp[i - 1][4]);
3、初始化:
dp[0][0] = 0;
dp[0][1] = -prices[0];第一次买入时手中的金额。
dp[0][2] = 0;第一次卖出。
dp[0][3] = -prices[0];第二次买入。
dp[0][4] = 0;
4、遍历顺序,因为dp[i] 由dp[i -1]推导出来,所以从i = 1开始从小到大去遍历。
5、打印dp数组。
代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>>dp(prices.size(), vector<int>(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][0] = dp[i - 1][0];
            dp[i][1] = max(dp[i - 1][1], 0 - prices[i]);
            dp[i][2] = max(dp[i - 1][2], dp[i - 1][1] + prices[i]);
            dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
            dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]); 
        }

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

    }
};

二、LeetCode188. 买卖股票的最佳时机 IV

题目链接:188. 买卖股票的最佳时机 IV
这道题的解法跟上道题类似,只不过需要将能买卖两天的所有状态变成能买卖k天的所有状态即可。
两次买卖的状态由22+1种,而买卖k次的状态共有2k+1种。
所以初始化时我们需要:

for(int i = 0; i <= 2 * k; i++) {
            if(i % 2 == 0) dp[0][i] = 0;
            else dp[0][i] = -prices[0];
        }

递推公式则是:

 if(j == 0) dp[i][j] = dp[i - 1][j];
 else {
     if(j % 2 == 1) {
        dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
     } else {
        dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + prices[i]);
       }
 }

代码如下:

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        vector<vector<int>>dp(prices.size(), vector<int>(2 * k + 1));//有2 * k + 1种状态
        for(int i = 0; i <= 2 * k; i++) {
            if(i % 2 == 0) dp[0][i] = 0;
            else dp[0][i] = -prices[0];
        }

        for(int i = 1; i < prices.size(); i++) {
            for(int j = 0; j <= 2 * k; j++) {
                if(j == 0) dp[i][j] = dp[i - 1][j];
                else {
                    if(j % 2 == 1) {
                        dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
                    } else {
                        dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + prices[i]);
                    }
                }
            }
        }
        // for(int i = 0; i < prices.size(); i++) {
        //     for(int j = 0; j <= 2 * k; j++) {
        //         cout<
        //     }
        //     cout<
        // }

        return dp[prices.size() - 1][2 * k];

    }
};

总结

如果不看题解感觉还是很困难的!

你可能感兴趣的:(C++算法题解,算法,leetcode,动态规划)