优化:
因为完成交易次数不会大于n/2
所以可以优化k = min(k,n/2);
少开一些空间,减少空间复杂度
示例1:
注意:最多可以完成k笔交易,不是必须k笔
1.状态表示
是什么?dp表中里的值所表示的含义就是状态表示
dp[i]表示:第i天结束之后,所能获得的最大利润
第i天结束后有两种状态,分别是“买入”状态和“卖出”状态,所以分为两个dp表
因为还要考虑交易次数的问题,所以每个表再加一维
f[i][j]表示:第i天结束之后,完成了j次交易,此时处于“买入”状态,此时最大利润
g[i][j]表示:第i天结束之后,完成了j次交易,此时处于“卖出”状态,此时最大利润
2.状态转移方程
dp[i] 等于什么
f[i][j] = max(f[i-1][j] , g[i-1][j]-p[i]);
g[i][j] = max(g[i-1][j], f[i-1][j-1] + p[i]);
转换一下:
g[i][j] = g[i-1][j]
if(j-1 >= 0) g[i][j] = max(g[i][j],f[i-1][j-1]+p[i])
3.初始化
保证填表的时候不越界
因为在卖出时才计算交易次数,所以在第0天是不会有1,2次交易的
所以设置为最小值,以不干扰结果,
但是可能涉及到+-运算,所以用INT_MIN的一半代替:-0x3f3f3f3f
4.填表顺序
为了填写当前状态的时候,所需要的状态已经计算过了
从上到下,每一行从左往右,两个表一起填
5.返回值
题目要求+状态表示
g表里的最后一行(n-1)的最大值(不一定是最后一次交易后)
6.代码
class Solution {
public:
const int INF = 0-0x3f3f3f3f;
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
k = min(k,n/2);
//1.创建dp表
vector<vector<int>>f(n,vector<int>(k+1,INF));
vector<vector<int>>g(n,vector<int>(k+1,INF));
//2.初始化
f[0][0] = 0-prices[0];
g[0][0] = 0;
//3.填表
for(int i = 1; i < n;i++)
{
for(int j = 0; j <= k ; j++)
{
f[i][j] = max(f[i-1][j], g[i-1][j]-prices[i]);
g[i][j] = g[i-1][j];
if(j-1 >= 0) //如果该状态存在
{
g[i][j] = max(g[i][j],f[i-1][j-1] + prices[i]);
}
}
}
//4.返回值
int ret = 0;
for(int j = 0; j <= k;j++)
{
ret = max(ret,g[n-1][j]);
}
return ret;
}
};