一、思路讲解
1. 当前操作
遍历到第i天时,根据当天是否持有股票,分别计算两种状态下的最大现金持有量(dp[i][0]表示第i天无股票时的最大现金,dp[i][1]表示第i天有股票时的最大现金)。
2. 子问题
已知前i-1天持有/不持有股票的最大现金(dp[i-1][0]和dp[i-1][1]),推导第i天持有/不持有股票的最大现金,最终通过最后一天不持有股票的最大现金(dp[n-1][0])得到最大收益(因为最后一天持有股票无法获利)。
3. 下一个子问题
- 若第
i天不持有股票:要么前一天也不持有(保持状态),要么前一天持有且当天卖出(卖出后现金增加当天股价); - 若第
i天持有股票:要么前一天已持有(保持状态),要么前一天不持有且当天买入(买入后现金减少当天股价)。
二、状态转移方程讲解
- 状态定义:dp[i][0]:第i天结束时不持有股票的最大现金;dp[i][1]:第i天结束时持有股票的最大现金。
- 状态转移:第i天不持有股票: dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]) 解释:取“前一天不持有股票的现金”和“前一天持有股票、当天卖出后现金(前一天持有现金+当天股价)”中的较大值。第i天持有股票: dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]) 解释:取“前一天持有股票的现金”和“前一天不持有股票、当天买入后现金(前一天不持有现金-当天股价)”中的较大值。
- 初始状态:第0天不持有股票:dp[0][0] = 0(无操作,现金为0);第0天持有股票:dp[0][1] = -prices[0](买入股票,现金为负的股价)。
最终结果取dp[n-1][0](最后一天不持有股票的最大现金),若结果为负则返回0(无收益)。
三、代码实现
#include <algorithm>
#include <vector>
class Solution {
public:
int maxProfit(vector<int>& prices) {
int m = prices.size();
vector<vector<int>>dp(m,vector<int>(2,0));// 枚举到第 i 天有股票/没有股票 手里的钱
// dp[i][0] 手里没有股票时,手里的钱 dp[i][1] 手里有股票时手里的钱
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1;i < m;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]);
}
return dp[m-1][0];
}
};
典型的状态机dp问题

京公网安备 11010502036488号