题目
我的思路
看到题目,基本确定要用动态规划。
我想到的状态转移的思路是:第i天结束后的最大利润是第i-1天的最大利润P(i-1)或者第j-1天的最大利润加上第j天买股票第i-1天卖股票的利润P(j)+Price(i)-Price(j)。
P(i)=P(i-1) P(i)=max(P(i),P(j,i-1)+P(j-1)),j<i-1 对于冷冻期的处理是假设卖出当天不能得到利润,冷冻期计算前一天的利润。所以在题目给的数组后追加一天作为最后一天结算的冷冻期来计算累计最大利润。我的实现
class Solution { public: int maxProfit(vector<int>& prices) { prices.push_back(0); vector<int> profit; profit.push_back(0);//第0天 for(int i=0;i<prices.size();i++){ profit.push_back(profit[i]); for(int j=0;j<i-1;j++){ if(profit[j]+prices[i-1]-prices[j]>profit[i+1]){ profit[i+1]=profit[j]+prices[i-1]-prices[j]; } } } return profit[prices.size()]; } }; //状态转移方程 /** P(i)=P(i-1) P(i)=max(P(i),P(j,i-1)+P(j-1)) P(i)是第i天能到手的最大利润,因为题目中有冷冻期机制,所以我们这里假定第i天能到手的利润是由第i-1天前的交易得到的,第i天处于冷冻期。又题目给出的最后一天卖出股票不需要冷冻期,为了便于计算,给数组追加一项作为冷冻期,价格是0。 //官方题解很奇妙 1.把每一天结束后分成三种状态,分别算三种状态下的最大收益。后一天的三种状态的最大收益由前一天决定! 2.时间复杂度和空间复杂度优化 vecotr容器变量插入新元素只能用push_back,不能用下标赋值;但是关联容器可以借助key来下标赋值 */
时间复杂度:n2,一共有n天,外循环一次计算每一天的最大利润,内循环遍历当前计算利润时刻以前的每一天。
空间复杂度:n,需要一个长度为n+1的数组来存储每一天的最大利润。
拓展学习
官方题解
官方题解的状态转移思路是每天分三种状态同时转移:当前持有一只股票、不持有股票并处于冷冻期中、不持有股票且不处于冷冻期中。
假如得到了前一天处于三种状态下各自的最大累计收益,就可以推算出当天的三种情况下的最大累计收益。也就是说第二天的最大累计收益一定是由第一天处于某一种最大累计收益状态下发展得到的。
class Solution { public: int maxProfit(vector<int>& prices) { if (prices.empty()) { return 0; } int n = prices.size(); // f[i][0]: 手上持有股票的最大收益 // f[i][1]: 手上不持有股票,并且处于冷冻期中的累计最大收益 // f[i][2]: 手上不持有股票,并且不在冷冻期中的累计最大收益 vector<vector<int>> f(n, vector<int>(3)); f[0][0] = -prices[0]; for (int i = 1; i < n; ++i) { f[i][0] = max(f[i - 1][0], f[i - 1][2] - prices[i]); f[i][1] = f[i - 1][0] + prices[i]; f[i][2] = max(f[i - 1][1], f[i - 1][2]); } return max(f[n - 1][1], f[n - 1][2]); } }; /**作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/solution/zui-jia-mai-mai-gu-piao-shi-ji-han-leng-dong-qi-4/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/