class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<int> dp(prices.size(), 0);
int m=0;
for(int i = 1; i < prices.size(); i++){
dp[i] = max(dp[i - 1] + prices[i] - prices[i - 1], prices[i] - prices[i - 1]);
if (dp[i] > m) m=dp[i];
}
return m;
}
};
这题笔者写的和随想录给的题解不太一样,由于只能卖出一次,所以dp中的数据不是到这一天时最大的收益,而是在这一天卖的情况下最大的收益,max中前一项本质上是记录着如果买卖并不是相邻两天时不断累计的收益,后者则是买卖为相邻两天的情况下的收益,如果后者大于前者,则说明前者买入的价格更低,自然也能获得更高的收益。
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(prices.size(), vector<int>(2, 0));
dp[0][0] -= prices[0];
for (int i = 1; i < prices.size(); 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[dp.size() - 1][1];
}
};
这题就是按随想录的题解写的了,两个max中的4个元素实际上就是4种动作,dp中第0列代表手里已买入股票,第1列代表手里没股票。第一个max中,前者是在前一天买入的情况下不卖出,后者是在前一天手里没股票的情况下买入,第二个max中,前者是在前一天手里没股票时保持不买,后者是在手里有股票时卖出。两个max就计算得出了第i天时,手里有股票和没股票两种情况下的最大收益,最终也就能在最后一天手里没股票时得出最大收益。
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<int> dp(4, 0);
dp[0] -= prices[0];
dp[2] -= prices[0];
for (int i = 1; i < prices.size(); i++){
dp[3] = max(dp[3], dp[2] + prices[i]);
dp[2] = max(dp[2], dp[1] - prices[i]);
dp[1] = max(dp[1], dp[0] + prices[i]);
dp[0] = max(dp[0], -prices[i]);
}
return dp[3];
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<int> dp(4, 0);
dp[0] -= prices[0];
dp[2] -= prices[0];
for (int i = 1; i < prices.size(); i++){
dp[0] = max(dp[0], -prices[i]);
dp[1] = max(dp[1], dp[0] + prices[i]);
dp[2] = max(dp[2], dp[1] - prices[i]);
dp[3] = max(dp[3], dp[2] + prices[i]);
}
return dp[3];
}
};
这题随想录给的题解就是吧dp数组的列数扩充,代表不同次数的买入卖出次数的状态,与上一题不同的是,这题中dp数组的计算是以左侧数据为计算的,而上一题则是两列交织计算,前者限制了交易次数不大于2,后者则对交易次数没有限制。笔者列了两个代码,随想录提过,后面那种写法看起来很简单但是有点蹊跷,就是从左向右进行计算,但之后的计算又要用到前面的数据,也就意味着后面对买入卖出的计算混入了当天的数据而非前一天,随想录从当天买入卖出等于不变的角度解释了,笔者再加一条,先计算的是当天买入的情况,如果买入发生变化,也就意味着当天的股票价格相较于前一天是下降的,所以当天不可能会卖出,所以卖出状态只会保持不变,而同一天买入卖出就是保持不变,所以即便混入了当天的数据也能得出正确结果。不过实际上从右向左计算也是对的,并且在逻辑上更加清晰。