代码随想录第29天 | 121. 买卖股票的最佳时机 、 122.买卖股票的最佳时机II

一、前言

参考文献:代码随想录

今天的主题是买股票,其中有一个题目只是前用用贪心算法做过的,但是这次是用动态规划,这里的难点还是对与递推公式的推导,我们一起来看看吧!

二、买卖股票的最佳时机

1、思路:

本题我一开始的想法与题解想法沾了一点边,但是并完全对;

(1)dp数组的确定:

        vector<vector<int>> dp (prices.size(), vector<int>(2, 0));

这个表示在第i天的时候dp[i][0]持有股票的利润和dp[i][1]不持有股票的利润;

持有股票可以分为两种,当天买入了股票和之前就持有股票;

不持有股票也分为两种,当天卖出了股票和之前就没有持有股票;

(2)递推公式:

注意!这里只允许买卖一次股票!

所以递推公式就是dp[i][0] 就可以由dp[i - 1][0]或者-prices[i]花掉买股票的钱,(我最开始的时候写的是dp[i - 1][1] - proces[i]这里就变成了多次买卖股票了!)我们只需要在这两者之前找到最大利润即可;

dp[0][1]同理:

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

(3)遍历顺序:

观察递推公式可知是从前向后遍历;

(4)初始化:

只需要初始化前一个dp就行

2、整体代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        // 与121的区别就是可以买卖多次
        // 1、创建dp数组
        vector<vector<int>> dp(prices.size(), vector<int>(2, 0));
        // 2、初始化
        // 买入股票
        dp[0][0] = -prices[0];
        // 不买
        dp[0][1] = 0;

        // 3、遍历顺序
        for (int i = 1; i < prices.size(); i++) {
            // 4、递推公式
            // 这里的主要区别就是可以去判断上一次是没买股票时的利润减去这次投资的本金
            dp[i][0] = max(dp[i - 1][1] - prices[i], dp[i - 1][0]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
        }

        // 4、打印dp数组
        // for (auto i : dp) {
        //     for (auto j : i) {
        //         cout << j << " ";
        //     }
        //     cout << endl;
        // }
        return dp[prices.size() - 1][1];
    }
};

三、买卖股票的最佳时机

1、思路:

本题与121差不多,只有一个地方不一样:本题可以买卖多次,这就表明递推公式会发生变化;

也就是在持有股票的时候发生变化:

dp[i][0] = max(dp[i -1][0], dp[i - 1][1] - prices[i]),这里买股票的时候就需要与之前不只有股票的利润就行运算了,而之前没有持有股票的话,那就是利润为0,因为只允许买卖一次;

2、整体代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        // 1、初始化dp数组
        // 在i天j = 0表示持有股表的利润dp[i][0],不持有股票的利润dp[i][1]
        vector<vector<int>> dp (prices.size(), vector<int>(2, 0));

        // 2、初始化
        dp[0][0] -= prices[0];
        dp[0][1] = 0;

        // 3、遍历顺序
        for (int i = 1; i < prices.size(); i++) {
            // 4、递推公式
            dp[i][0] = max(-prices[i], dp[i - 1][0]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
        }

        // 5、打印dp数组
        // for (auto j : dp) {
        //     for (auto k : j) {
        //         cout << k << " ";
        //     }
        //     cout << endl;
        // }

        return dp[prices.size() - 1][1];

    }
};

Time to Study: 1h

leave message:

 A little kownledge is not a dangerous thing to one who does not mistake it for a great deal.

知识浅薄对一个人并不危险,只要他不误以为知识渊博。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值