zoukankan      html  css  js  c++  java
  • LeetCode309. 最佳买卖股票时机含冷冻期

    状态机dp,可以参考LeetCode188. 买卖股票的最佳时机 IV.

    我们可以用一个数组dp[n][2]表示每一个状态下的最高收益(其中n是prices数组的大小,即总的天数)。
    数组的第一维表示天数,第二维表示持有或不持有股票(1表示持有,0表示不持有)能获得的最大收益。
    比如dp[i][0]表示第i天,不持有股票的最高收益,dp[i][1]表示第i天,持有股票的最高收益。

    对于一个不持有股票的状态dp[i][0],它由两种状态转移而来,即(1)前一天也不持有股票,今天什么都没做,这种情况下我们有: dp[i][0] = dp[i - 1][0];
    (2)前一天持有股票,今天把股票卖了,这种情况下我们有:dp[i][0] = dp[i - 1][1] + prices[i]; 加上prices[i]表示卖出股票增加了prices[i]的收益。
    由于我们的dp数组表示的是某状态下的最高收益,因此我们需要对上面的两个状态取一个max: dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);

    对于一个持有股票的状态dp[i][1],它也由两种状态转移而来,即(1)前一天就持有股票,今天什么都没做,这种情况下我们有: dp[i][1] = d[i - 1][1];
    (2)前两天不持有股票,今天买了一只股票(由于有一天的交易冷冻期,所以不能是昨天买的股票,而是前天买的),这种情况下我们有: dp[i][1] = dp[i - 2][0] - prices[i];
    减去prices[i]表示我们花了prices[i]的价格/成本买了一只股票。
    由于我们的dp数组表示的是某状态下的最高收益,因此我们需要对上面的两个状态取一个max: dp[i][1] = max(dp[i - 1][1], dp[i - 2][0] - prices[i]);

    有了状态转移方程,我们再考虑一下递推边界,由于状态转移方程中用到了dp[i - 1][]和dp[i - 2][],所以对于i为0和i为1的情况我们要单独处理,以防数组越界。

    状态dp[0][0]表示第0天,不持有股票,显然dp[0][0] = 0;
    状态dp[0][1]表示第0天,持有股票,也就是第0天花了prices[0]的价格买了一只股票,我们有:dp[0][1] = -prices[0];
    状态dp[1][0]表示第1天,不持有股票,这有两种情况:(1)第0天和第1天什么都没做:dp[1][0] = 0; (2)第0天买入股票,第1天卖出: dp[0][1] = -prices[0] + prices[1];
    同样的,状态要取两者中的较大值: dp[0][1] = max(0, -prices[0] + prices[1]);
    状态dp[1][1]表示第1天,持有股票,这也有两种情况:(1)第0天买了只股票,第1天什么都没做:dp[1][1] = -prices[0]; (2)第0天什么都没做,第1天买了只股票:dp[1][1] = -prices[1];
    同样的,状态要取两者中的较大值: dp[1][1] = max(-prices[0], -prices[1]);

    有了递推边界和状态转移方程之后,我们就可以开始状态转移了。

    最后的答案就是dp[n - 1][0],表示最后一天,不持有股票,所能获得的最高收益。
    为什么不是dp[n - 1][1]呢?因为股票卖出去肯定比拿在手里的钱多,毕竟买股票要钱,交易掉还能赚差价呢。
    所以显然dp[n - 1][0]的值大于dp[n - 1][1]。
    最终答案就是dp[n - 1][0]。

    代码如下:

    class Solution {
    public:
        int maxProfit(vector<int>& prices) {
            int n = prices.size();
            if(n < 2) {
                return 0;
            }
            vector<vector<int>> dp(n, vector<int>(2));
            dp[0][0] = 0;
            dp[0][1] = -prices[0];
            dp[1][0] = max(0, -prices[0] + prices[1]);
            dp[1][1] = max(-prices[0], -prices[1]);
            for(int i = 2; i < n; ++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 - 2][0] - prices[i]);
            }
            return dp[n - 1][0];
        }
    };
    
  • 相关阅读:
    iOS仿UC浏览器顶部频道滚动效果
    OC中NSClassFromString()与NSStringFromClass()的用法及应用场景
    利用工具MailUtils实现邮件的发送,遇到的大坑,高能预警!!
    使用response实现文件下载注意点
    mac版MyEclipse的安装及创建web项目
    Mac系统下安装Tomcat,以及终端出现No such file or directory的错误提示解决方案
    机器学习笔记-Python简介
    解决mscordacwks.dll不一致问题
    IIS日志如何记录X-Forwarded-For
    深入理解Redis(番外)——持久化
  • 原文地址:https://www.cnblogs.com/linrj/p/13458596.html
Copyright © 2011-2022 走看看