Coding | [代码随想录][动态规划] 122.买卖股票的最佳时机Ⅱ —— 从强行dp到对二维状态的理解

题面

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

思路

点进力扣一看发现是之前贪心做过的题目。这道题和股票1这道题目的区别就在于可以多次购买这一支股票,那其实每一次都把两天之间赚来的钱算进去就行,大不了理解为同一天内先卖出再买入罢了。但是当我尝试着用Carl所讲的动态规划去手动演算这个过程的时候,我慢慢理解了在股票Ⅰ的时候我所不理解的点。

以往不管我做题的时候用的到底是几维的dp数组去表示动态规划过程,我都没有领悟到这一点:动态规划能运行的前提是状态最少能用几个维度去唯一表征一个状态,就可以使用几维dp数组。并且还必须满足:①之前是如何(通过什么路径)到达该状态的并不重要;②状态代表了之前所有路径到达该状态的最优值,并且之前的路径不会对状态之后的状态转移有影响。

这道题,光靠时间可以确定当前状态吗?很明显不行,那么第二维度是什么呢?

Carl说:是股票的持有情况。

这样一来,买入、卖出、持有股票未变动、未持有股票未变动就都能通过这个维度的变化来表示了。

遍历时间维度,通过处理dp[i][1]——第i天持有股票的最优情况,以及dp[i][0]——第i天未持有股票的情况,便能够确定第i天的所有情况,换句话说,保留了第i天的最佳情况集合。之后无论是什么动作(买入、卖出、持有股票未变动、未持有股票未变动),都是由这两个状态计算得出的。

而——这两个状态的计算,同样需要考虑:如何到达这个状态?

都是两个状态转移情况:

dp[i][1]:买入(dp[i-1][0] - prices[i]) 或 持有股票未变动(dp[i-1][1])

dp[i][0]:卖出(dp[i-1][1] + prices[i]) 或 未持有股票未变动(dp[i-1][0])

考虑:①之前是如何(通过什么路径)到达该状态的并不重要;②状态代表了之前所有路径到达该状态的最优值,并且之前的路径不会对状态之后的状态转移有影响。

——是满足的!

那就考虑对两个状态分别取最大值作为其最优状态,来表示这一天的最佳情况集合。这也成为了我们的状态转移方程。

其实还可以发现,最后一天还保有股票的这种情况完全可以不计算。

题解

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(prices.size(), vector<int>(2, INT_MIN));
        for(int i = 0; i < dp.size(); i++){
            if(i == 0){
                dp[i][0] = 0;
                dp[i][1] = -prices[0];
            }
            else{
                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]));
            }
        }
        return dp[dp.size() - 1][0];
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值