当前位置: 首页 > article >正文

代码随想录算法训练营第50天|123.买卖股票的最佳时机III,188.买卖股票的最佳时机IV

代码随想录算法训练营第50天|123.买卖股票的最佳时机III,188.买卖股票的最佳时机IV

  • 123.买卖股票的最佳时机III
  • 188.买卖股票的最佳时机IV

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

题目链接:123.买卖股票的最佳时机III,难度:困难
【实现代码】

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.size() == 1) {
            return 0;
        }
        vector<vector<int>> dp(prices.size(), vector<int>(5, 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], -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.back().back();
    }
};

【解题思路】

动态规划五部曲:

  1. 确定dp数组以及下标的含义:
    一天一共就有五个状态,
  • 0:没有操作 (其实我们也可以不设置这个状态)
  • 1:第一次持有股票
  • 2:第一次不持有股票
  • 3:第二次持有股票
  • 4:第二次不持有股票
    dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
  1. 确定递推公式
    达到dp[i][1]状态,有两个具体操作:
  • 操作一:第i天买入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]
  • 操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]
    一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);
    同理dp[i][2]也有两个操作:
  • 操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
  • 操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]
    所以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][4], dp[i - 1][3] + prices[i]);
  1. dp数组如何初始化:dp[0][0] = 0; dp[0][1] = -prices[0]; dp[0][2] = 0; dp[0][3] = -prices[0]; dp[0][4] = 0;
  2. 确定遍历顺序:递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。
  3. 举例推导dp数组

188.买卖股票的最佳时机IV

题目链接:188.买卖股票的最佳时机IV,难度:困难
【实现代码】

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if (prices.size() == 0) {
            return 0;
        }
        vector<vector<int>> dp(prices.size(), vector<int>(k * 2 + 1, 0));
        for (int i = 1; i <= k * 2; i += 2) {
            dp[0][i] = -prices[0];
        }
        for (int i = 1; i < prices.size(); i++) {
            for (int j = 1; j <= k * 2; j += 2) {
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
                dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] + prices[i]);
            }
        }
        return dp.back().back();
    }
};

【解题思路】

动态规划五部曲:

  1. 确定dp数组以及下标的含义:dp[i][j] :第i天的状态为j,所剩下的最大现金是dp[i][j],j的范围就定义为 2 * k + 1 ,除了0以外,偶数就是卖出,奇数就是买入。
  2. 确定递推公式
    达到dp[i][1]状态,有两个具体操作:
  • 操作一:第i天买入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]
  • 操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]
    一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);
    同理dp[i][2]也有两个操作:
  • 操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
  • 操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]
    所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])
  1. dp数组如何初始化:dp[0][j]当j为奇数的时候都初始化为 -prices[0]
  2. 确定遍历顺序:递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。
  3. 举例推导dp数组

http://www.kler.cn/a/13514.html

相关文章:

  • 【设计模式】深入浅出--外观模式
  • Unity日记22(携程概念)
  • 2023 腾讯暑期实习申请经验分享
  • 技术干货|直流电源自动测试系统功能介绍
  • Docker网络详解
  • FreeRTOS学习笔记(一)——初识FreeRTOS
  • 分享下这些软件外包公司(2023最新版),程序员有福了
  • 程序员跳槽,要求涨薪50%过分吗?
  • 【存储技术分享】SGL和SGE
  • ERTEC200P-2 PROFINET设备完全开发手册(9-2)
  • 性能测试:深入理解线程数,并发量,TPS,看这一篇就够了
  • [java/初学者]java常用API(2)——字符串
  • leetcode551. 学生出勤记录 I
  • 小程序弹框的一些总结
  • 总结827
  • Mysql中的三种log原理
  • 句子改写神器-文案自动改写的免费软件
  • SLAM论文速递【SLAM—— PLD-SLAM:一种基于点线特征的室内动态场景RGB-D SLAM新方法—4.23(1)
  • 如何提高代码能力:程序员的成长之路(下)
  • C/C++每日一练(20230423)