在这道题目要求计算单次买卖能得到的最大利润,单次买卖的最大利润首先想到寻找最低股价买入,然后在最高股价时卖出。但是如果最低股价出现在最高股价的后面(时间上)呢?因此我们修改求解方法,单次买卖的最大利润需要寻找最低股价买入,然后在最低股价之后的天数中寻找最高股价时卖出;或者先寻找最高股价,然后从最高股价向前寻找最低股价。
在这道题目中,我们可以假设每一天都存在两种状态,持有股票和不持有股票。我们获取利润的过程也就是从不持有股票到持有股票(买入),再到不持有股票的过程(卖出)。因此我们有两种操作,买入和卖出,同时想到我们可以保持原有状态不操作,因此还有保持操作。
当天不持有股票的现金=MAX(前一天不持有股票的现金(保持)+(前一天持有股票的现金+当天股价)(卖出))
当天持有股票的现金=MAX(前一天持有股票的现金(保持)+(前一天不持有股票的现金-当天股价)(卖出))
更进一步,因为本题只允许单次买卖,所有前一天不持有股票的现金始终为0。经过化简可以将,当天不持有股票的现金等价于最大利润,初始为0代表不进行买卖时的利润是0不可能更低。当天持有股票的现金等价于最低买入价格,因为不发生多次买卖。
画出状态变化图辅助理解:
第i天 | 股票价格 | 买入 | 卖出 |
0 | 0 | ||
0 | 7 | -7 | 0 |
1 | 1 | max(-1, -7)=-1 | max(-7+1, 0)=0 |
2 | 5 | -1 | 4 |
3 | 3 | -1 | 2 |
4 | 6 | -1 | 5 |
5 | 4 | -1 | 3 |
给出leetcode提交代码,代码参考代码随想录。
// leetcode上提交的代码
class Solution {
public:
int maxProfit(vector<int>& prices)
{
vector<int> dp(2, 0);
dp[0]=-prices[0]; // 对第0天初始化,仅考虑买入,因为无法卖出
for(int i=1;i<prices.size();i++)
{
// 找最低买入价格
int temp = max(dp[0], -prices[i]);
// 找最高买卖利润
dp[1]=max(dp[1], dp[0]+prices[i]);
dp[0]=temp;
}
return dp[1];
}
};