题面
给你一个整数数组 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];
}
};

被折叠的 条评论
为什么被折叠?



