代码随想录算法训练营Day-41动态规划08 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III

121. 买卖股票的最佳时机

**1.dp数组含义:**dpi0、dpi1分别代表第i天,不持有股票和持有股票获得的最大价值;

2.递推公式:

不持有股票:dpi0 = max(dpi-10, dpi-11+pricesi)

两种情况,1. 第i-1天就没有持有股票,第i天不操作,所以延续不持有的价值;2. 第i-1天持有股票了,到第i天卖出,导致第i天不持有,所以是 dpi-11+pricesi。两种情况取最大值。

持有股票:dpi1 = max(dpi-11, -pricesi)

两种情况,1. 第i-1天就持有股票,第i天不操作,所以延续持有的价值;2. 第i-1天不持有股票,到第i天买入,导致第i天持有,所以是 -pricesi。两种情况取最大值。

**3.初始化:**只需初始化第0天持有或不持有手中的价值,分别是-prices0和0

**4.遍历顺序:**顺序遍历,从1到尾索引;

注:由于递推只用到了dpi-1,所以可以只创建大小为2*2的数组,滚动更新第i-1天和第i天即可,通过取模实现。

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(2, vector<int>(2));

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

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

122.买卖股票的最佳时机II

和上一题的区别在于:本题可以多次买卖,因此对于第i天持有股票了来说,不一定是第几次持有,所以买入第i天股票时手里的钱不确定是不是0,所以持有股票的递推公式需要改为

cpp 复制代码
dp[i][1] = max(dp[i-1][1], -prices[i]);

应改为:

cpp 复制代码
dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]);
cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(2, vector<int>(2));

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

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

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

和前两题区别在于,本题最多只能买卖两次,所以全部覆盖状态比较多,需要分成dpi0、dpi1、dpi2、dpi3、dpi4,分别代表第i天不操作、第一次持有、第一次不持有、第二次持有、第二次不持有;

**递推公式:**dpi0延续即可;dpi1由第i-1天的1延续而来,或者0买入;dpi2由第i-1天的2延续而来,或者1卖出;dpi3由第i-1天的3延续而来,或者2买入;dpi4由第i-1天的4延续而来,或者3卖出;

**初始化:**只需要考虑第0天的五种状态,只有持有的时候才会不是0,呈现出负的第一天股票价格,其余都相当于同一天多次买卖,不持有股票,即为0;

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(2, vector<int>(5,0));

        dp[0][1] = -prices[0];//第一次持有
        dp[0][3] = -prices[0];//第二次持有

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

相关推荐
左手の明天31 分钟前
SLIP 协议封装与解析详解:原理、C 代码与实战案例
linux·c语言·开发语言·c++
nhdh35 分钟前
B+树揭秘:MySQL索引核心原理全解析
数据结构·b树·mysql
海上小飞龙1 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
青少儿编程课堂1 小时前
后缀自动机解析:本质不同子串与最长重复片段统计
c++·python·算法·bfs·信息学竞赛
朝朝辞暮i1 小时前
C++ 第 12 课:局部变量、作用域、变量生命周期
开发语言·c++·算法
乐迪信息2 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
无名猿3 小时前
shared_ptr 完全指南:引用计数、控制块与开销
c++·性能优化·内存管理·标准库·现代c++
Sirens.3 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
和裕4 小时前
全纸结构重型纸箱能否满足 1 吨以上设备出口熏蒸豁免要求?通关合规性全解析
大数据·运维·网络·人工智能·算法