动态规划第一步:确定dp数组以及下标的含义
因为本题中说明只进行一次买卖,即一次买一次卖,所以有dp【i】【0】和dp【i】【1】两种状态,dp数组大小为prices数组的大小。
dp【i】【0】:第i天的第0种状态,而0代表手里已持有股票,虽然我持有,但我不一定是今天持有的,也可能是昨天持有,前天持有,只表面我现在持有股票。
dp【i】【1】:第i天的第1种状态,而1代表手里未持有股票,同上所述;我可能是今天未持有,也可能是以前就未持有。
动态规划第二步,确定递推公式
dp【i】【0】以上所述,可以由两种情况演变而来:
dp【i-1】【0】:由第i-1天状态推导而来,延续这个状态,即没有进行操作。
-prices【i】:第i天进行了操作,购入股票,当前手里的现金为-prices【i】。
所以dp【i】【0】 =max(dp【i-1】【0】,-prices【i】)
dp【i】【1】以上所述,可以由两种情况演变而来:
dp【i-1】【1】:由第i-1天状态推导而来,延续这个状态,即没有进行操作。
prices【i】:第i天进行了操作,卖出股票,当前手里的现金为dp【i-1】【0】+prices【i】,即前一天的现金加上今天卖出股票的现金。
所以dp【i】【1】 =max(dp【i-1】【1】,dp【i-1】【0】+prices【i】)
动态规划第三步,dp数组初始化
需要初始化的数据为dp【0】【0】,dp【0】【1】
dp【0】【0】= -prices【0】,0代表已持有,而现在的已持有不可能由i-1推出来,所以是购入prices【0】的股票。
dp【0】【1】,1代表未持有,第0天未持有表示没有盈利,现金为0。
动态规划第四步,确定遍历顺序
因为第i天的状态要由i-1天推导而来,所以是从前往后遍历。
动态规划第五步,打印dp数组(纠错)
完整代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int len = prices.size();
if (len==0) return 0;
vector<vector<int>> dp(len,vector<int>(2));
dp[0][0] -= prices[0];
dp[0][1] = 0;
for(int i=1;i<len;i++){
dp[i][0] = max(dp[i-1][0],-prices[i]);
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i]);
}
return dp[len-1][1];
}
};
时间复杂度O(n)
空间复杂度O(n)