动态规划dp —— 18.买卖股票的最佳时机 IV

优化:

因为完成交易次数不会大于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;

    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值