经典讲解https://www.cnblogs.com/Bella2017/p/11277064.html
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
示例 1:
输入: [7,1,5,3,6,4]
输出:5
状态机模型如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dp_i_0 = 0, dp_i_1 = INT_MIN; //base case
for(int i=0; i<prices.size(); ++i){
dp_i_1 = max(dp_i_1, -prices[i]);
dp_i_0 = max(dp_i_0, dp_i_1+prices[i]);
}
return dp_i_0;
}
};
个人的理解:
dp[n][k][0]表示第n天,如果最多允许k次交易且手上这天没股票的情况下的最大利润
dp[n][k][1]表示第n天,如果最多允许k次交易且手上这天有股票的情况下的最大利润
那么,
dp[n][k][0] = max(dp[n-1][k][0], dp[n-1][k][1] + prices[i])
// 卖股票
dp[n][k][1] = max(dp[n-1][k][1], dp[n-1][k-1][0] - prices[i])
// 买股票,这相当于一次新交易
当k = 1的时候
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], -prices[i])
有个问题啊,为啥我之前把计算dp_i_0和dp_i_1的公式写反了还是对的呢?
这个和公式的特性有关,下面是先算dp_i_1的结果
代码1
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dp_i_0 = 0, dp_i_1 = INT_MIN; //base case
for(int i=0; i<prices.size(); ++i){
dp_i_1 = max(dp_i_1, -prices[i]);
dp_i_0 = max(dp_i_0, dp_i_1+prices[i]);
}
return dp_i_0;
}
};
和代码2
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dp_i_0 = 0, dp_i_1 = INT_MIN; //base case
for(int i=0; i<prices.size(); ++i){
dp_i_0 = max(dp_i_0, dp_i_1+prices[i]);
dp_i_1 = max(dp_i_1, -prices[i]);
}
return dp_i_0;
}
};
我们觉得可能出问题的点在于先算dp_i_1,可能dp_i_0的值会受到影响
那我们看看实际情况下真的会受影响吗
假设dp_i_1变大,
对于代码1, dp_i_0是不变的
对于代码2 dp_i_0也是不变的
所以没有影响
引申:
309. Best Time to Buy and Sell Stock with Cooldown
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = max(dp[i-1][1], dp[i-2][0] - prices[i]); // 注意,由于cooldown机制的存在,不能是i-1
714. Best Time to Buy and Sell Stock with Transaction Fee
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i] + fee);
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]);
123. Best Time to Buy and Sell Stock III
int maxProfit(vector<int>& prices) {
int dp10 = 0;
int dp11 = INT_MIN;
int dp20 = 0;
int dp21 = INT_MIN;
for (int price: prices)
{
dp20 = max(dp20, dp21 + price);
dp21 = max(dp21, dp10 - price);
dp10 = max(dp10, dp11 + price);
dp11 = max(dp11, -price );
}
return dp20;
}
188. Best Time to Buy and Sell Stock IV
vector<int> dp0(k+1, 0);
vector<int> dp1(k+1, INT_MIN);
for (int num: nums)
{
for (int i = 1; i <= k; i++)
{
dp0[i] = max(dp0[i], dp1[i] + num);
dp1[i] = max(dp1[i], dp0[i-1] - num);
}
}