动态规划Day30:买卖股票

121. 买卖股票的最佳时机

贪心法

取左边最小的,记录出现过的最大差值

cpp 复制代码
int maxProfit(vector<int>& prices) {
        int low = INT_MAX;
        int result = INT_MIN;
        for(int price: prices){
            low = min(low, price);
            result = max(result, price - low);
        }
        return result;
    }

动态规划

状态 0 :第 i 天结束后,不持有股票的最大利润。

状态 1 :第 i 天结束后,持有股票的最大利润。

dp[i][0] 表示第 i 天不持有股票的最大利润,dp[i][1] 表示第 i 天持有股票的最大利润。

状态 0(不持有股票)的两种可能:

情况 1:第 i-1 天就不持有股票,第 i 天啥也没做,利润不变 → dp[i][0] = dp[i-1][0]

情况 2:第 i-1 天持有股票,第 i 天卖出了,利润 = 前一天持有股票的利润 + 当天股价 → dp[i][0] = dp[i-1][1] + prices[i]

综上,dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])(取两种情况的最大值)。

状态 1(持有股票)的两种可能:

情况 1:第 i-1 天就持有股票,第 i 天啥也没做,利润不变 → dp[i][1] = dp[i-1][1]

情况 2:第 i 天是第一次买入股票,利润 = - 当天股价(因为买入要花钱,利润为负) → dp[i][1] = -prices[i]

综上,dp[i][1] = max(dp[i-1][1], -prices[i])(取两种情况的最大值,本质是找「最便宜的买入价」)。

初始化状态

第 0 天(第一天):

不持有股票:没买也没卖,利润为 0 → dp[0][0] = 0

持有股票:第一天买入,利润为 -prices[0]dp[0][1] = -prices[0]

cpp 复制代码
int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(prices.size(), vector<int>(2, 0));
        if(prices.size() == 0){
            return 0;
        }
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for(int i = 1; i < prices.size(); i++){
            //不持有股票的最大利润
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            //持有股票的最大利润
            dp[i][1] = max(dp[i - 1][1], -prices[i]);
        }
        return dp[prices.size() - 1][0];
    }

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

贪心法

cpp 复制代码
    int maxProfit(vector<int>& prices) {
        int res = 0;
        for(int i = 1; i < prices.size(); i++){
            if(prices[i] - prices[i - 1] > 0){
                res += prices[i] - prices[i - 1];
            }
        }
        return res;
    }

动态规划

与上题类似,只是允许多次买卖

所以在买入股票需要叠加之前获得的最大利润

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

cpp 复制代码
    int maxProfit(vector<int>& prices) {
       vector<vector<int>> dp(prices.size(), vector<int>(2));
       if(prices.size() == 0){
        return 0;
       }
       dp[0][0] = 0;
       dp[0][1] = -prices[0];
       for(int i = 1; i < prices.size(); 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]);
       }
       return dp[prices.size() - 1][0];
    }

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

有五种状态:

没有操作

第一次持有股票

第一次不持有股票

第二次持有股票

第二次不持有股票

cpp 复制代码
    int maxProfit(vector<int>& prices) {
        vector<vector<int>>dp(prices.size(), vector<int>(5));
        if(prices.size() == 0){
            return 0;
        }
        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];//不操作一直是0
            dp[i][1] = max(dp[i - 1][1], dp[i - 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];

    }

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

是上题的扩展,有k次买 k次卖,就有2 * k + 1个状态,第一个状态为不操作,其余是第i次持有,以及第i次不持有

cpp 复制代码
int maxProfit(int k, vector<int>& prices) {
        vector<vector<int>>dp(prices.size(), vector<int>(2*k + 1));
        if(prices.size() == 0){
            return 0;
        }
        for(int i = 1; i < 2*k + 1; i++){
            if(i % 2 == 1){
                dp[0][i] = -prices[0];
            }else {
                dp[0][i] = 0;
            }
        }
        for(int i = 1; i < prices.size(); i++){
            dp[i][0] = 0;
            for(int j = 1; j < 2*k + 1; j++){
                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]);
                }
            }
        }
        return dp[prices.size() - 1][2 * k];
    }

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

分成四个状态:

今天持有股票:

继承昨日已买的股票

今日买股票

今天卖出股票

今天继续不买股票(非冷冻期):

昨日冷冻期

昨日非冷冻期

今天冷冻期

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size() <= 1){
            return 0;
        }
        vector<vector<int>> dp(prices.size(), vector<int>(4, 0));
        //四种状态:今天持有股票,今天卖出,今天保持不买(非冷冻期),今天冷冻期
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        dp[0][2] = 0;
        dp[0][3] = 0;
        for(int i = 1; i < prices.size(); i++){
            dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][2] - prices[i], dp[i - 1][3] - prices[i]));
            dp[i][1] = dp[i - 1][0] + prices[i];
            dp[i][2] = max(dp[i - 1][2], dp[i - 1][3]);
            dp[i][3] = dp[i - 1][1];
        }
        return max(dp[prices.size() - 1][1],max(dp[prices.size() - 1][2], dp[prices.size() - 1][3]));

    }
};

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

与第二题类似,只是卖出的时候多扣一个手续费

cpp 复制代码
    int maxProfit(vector<int>& prices, int fee) {
        if(prices.size() <= 1){
            return 0;
        }
        vector<vector<int>>dp(prices.size(), vector<int>(2, 0));
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i = 1; i < prices.size(); 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);
        }
        return dp[prices.size() - 1][1];
    }
相关推荐
CoovallyAIHub8 小时前
181小时视频丢给GPT-5,准确率只有15%——南大联合NVIDIA等五校发布多模态终身理解数据集
深度学习·算法·计算机视觉
CoovallyAIHub9 小时前
CVPR 2026 | GS-CLIP:3D几何先验+双流视觉融合,零样本工业缺陷检测新SOTA,四大3D工业数据集全面领先!
深度学习·算法·计算机视觉
有意义11 小时前
深度拆解分割等和子集:一维DP数组与倒序遍历的本质
前端·算法·面试
用户7268761033712 小时前
解放双手的健身助手:基于 Rokid AR 眼镜的运动计时应用
算法
Wect13 小时前
LeetCode 17. 电话号码的字母组合:回溯算法入门实战
前端·算法·typescript
ZhengEnCi1 天前
08c. 检索算法与策略-混合检索
后端·python·算法
程序员小崔日记1 天前
大三备战考研 + 找实习:我整理了 20 道必会的时间复杂度题(建议收藏)
算法·408·计算机考研
lizhongxuan1 天前
AI小镇 - 涌现
算法·架构
AI工程架构师2 天前
通常说算力是多少 FLOPS,怎么理解,GPU和CPU为什么差异这么大
算法