代码随想录 11.11 || 动态规划 LeetCode 309.买卖股票的最佳时机含冷冻期、714.买卖股票的最佳时机含手续费

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

        给定一个整数数组 prices,其中第 prices[i] 表示第 i 天的股票价格。设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一只股票):卖出股票后,你无法在第二天买入股票(即冷冻期为一天)。注意:你不能同时参与多笔交易(必须在再次购买前出售掉之前的股票)。

        与之前的买卖股票问题不同,本题要求在卖完股票后,存在一天的冷冻期,不得立马购入股票。下面从动态规划五部曲仔细分析该题:

        1. 定义 dp 数组的含义,我们定义 dp[i][j] 为第 i 天的第 j 种状态的最大利润;

        2. 确定递推公式,我们将每天的状态划分如下:持有(买入)股票;不持有股票;卖出股票;冷冻期。(状态 0 ~ 3)

        对应的递推公式分别为:

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

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

        dp[i][2] = dp[i - 1][0] + prices[i];

        dp[i][3] = dp[i-1][2]。

        状态 0 能由状态 0、1、3 推导,无法由状态 3 推导得到,因为卖出股票后无法立即买入;状态 1 能由状态 1、2、3 推导,不持有股票的前一天可能为不持有股票、卖出股票和冷冻期状态;状态 2 仅能由状态 0 推导,卖出的前一天必定是持有(买入)股票状态;状态 4 必由状态 2 推导,冷冻期前一天必为卖出。

        3. 初始化,dp[0][0] = -prices[i],dp[0][1~3] = 0;

        4. 遍历顺序,从前向后;

        5. 出错时,打印 dp 数组 debug。

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int len = prices.size();
        if (len == 0) return 0;

        vector<vector<int>> dp(len, 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 < len; ++i) {
            dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][1] - prices[i], dp[i - 1][3] - prices[i]));
            dp[i][1] = max(dp[i - 1][1], max(dp[i - 1][2], dp[i - 1][3]));
            dp[i][2] = dp[i - 1][0] + prices[i];
            dp[i][3] = dp[i - 1][2];
        }

        return max(dp[len - 1][1], max(dp[len - 1][2], dp[len - 1][3]));
    }
};

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

        只要减去手续费即可,因为有手续费的存在,所以不交易可能比交易的获利更大,所以取 dp[len - 1][0] 和 dp[len - 1][1] 的最大值。

class Solution {
public:
    int maxProfit(vector<int> &prices, int fee) {
        int len = prices.size();
        if (len == 0) return 0;

        vector<vector<int>> dp(len, vector<int>(2, 0));
        dp[0][0] = 0 - prices[0]; dp[0][1] = dp[0][0] + prices[0];

        for (int i = 1; i < len; ++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 max(dp[len - 1][0], dp[len - 1][1]);
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值