• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

RomanLin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【状态机DP】LeetCode 123. 买卖股票的最佳时机|||

前言

状态机 DP是一种特殊的动态规划方法,它将问题建模为一个状态机(有限状态自动机),然后在这个状态机上进行状态转移。

状态机三要素

  1. 状态划分(互斥状态)
  2. 转移规则(状态机图)
  3. 资源约束(次数限制)

题目

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/

题解

第一步,进行状态划分,找到互斥的状态:
总共有 \(n\) 天,可以完成两笔交易,每天至多操作一次(买入/卖出)。因此可以定义出以下五种状态:

  1. 未进行过任何交易(没有操作也是一种操作)
  2. 执行了第一笔交易的买入
  3. 在已经执行了第一笔交易的买入的基础上,执行第一笔交易的卖出
  4. 在已经执行了第一笔交易的卖出的基础上,执行第二笔交易的买入
  5. 在已经执行了第二笔交易的买入的基础上,执行第二笔交易的卖出

第二步,制定转移规则,设计状态机图:
状态机.drawio

第三步,明确资源约束条件
该题的资源约束条件是限制交易次数为至多两次,也就是任意一次操作必须符合第一步定义的五种状态之一。

定义 \(dp[i][j]\) 为在前 \(i\) 天状态为第 \(j\) 种状态。

由状态机图,可列出以下状态转移方程:

dp[i + 1][0] = max(dp[i][0], -prices[i]);
dp[i + 1][1] = max(dp[i][1], prices[i] + dp[i][0]);
dp[i + 1][2] = max(dp[i][2], -prices[i] + dp[i][1]);
dp[i + 1][3] = max(dp[i][3], prices[i] + dp[i][2]);

参考代码

朴素 DP 版本

时间复杂度:\(O(n)\)
空间复杂度:\(O(4 \times n)\)

constexpr int INF = -1e9;
int dp[100001][4] = {INF, INF, INF, INF};

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

空间优化版本

时间复杂度:\(O(n)\)
空间复杂度:\(O(1)\)

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        int buy1 = -1e9, buy2 = -1e9;
        int sell1 = 0, sell2 = 0;
        for (int i = 0; i < n; ++ i) {
            sell1 = max(sell1, prices[i] + buy1);
            buy1 = max(buy1, -prices[i]);
            sell2 = max(sell2, prices[i] + buy2);
            buy2 = max(buy2, sell1 - prices[i]);
        }
        return sell2;
    }
};

posted on 2026-02-08 22:29  RomanLin  阅读(0)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3