代码随想录|day50|动态规划part11● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV

123.买卖股票的最佳时机III

链接:代码随想录

这道题一下子就难度上来了,关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。

 

 直接看答案,五种状态,清晰明白。

 状态转移方程比较好想,初始值并不太好想。

具体来说:

基本明白思路后能一次写出 

class Solution {
    /*
    dp[i][0] 不操作
    dp[i][1]  第一次持有股票
    dp[i][2]  第一次不持有股票
    dp[i][3]  第二次持有股票
    dp[i][4]  第二次不持有股票


递推公式:
    dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
    dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i]);
    dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i]);
    dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i]);

初始值:------------------啊啊啊啊好难想
   当i=0时,
    dp[0][0]------------------不操作,等于0
    dp[0][1]------------------第一次持有股票,等于 -prices[0]
    dp[0][2]-------------------0
    dp[0][3]                   -prices[i]或者0
    dp[0][4]                   prices[i]或者0
  
    */
public:
    int maxProfit(vector<int>& prices) {
        int n=prices.size();
        vector<vector<int>>dp(n,vector<int>(5,0));
        //初始化
        dp[0][0]=0;
        dp[0][1]=-prices[0];
        dp[0][2]=0;
        dp[0][3]=-prices[0];
        dp[0][4]=0;

        for(int i=1;i<n;i++)
        {
             dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);
             dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i]);
             dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i]);
             dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i]);
        }
        


       return dp[n-1][4];



    }
};

188.买卖股票的最佳时机IV

本题是123.买卖股票的最佳时机III 的进阶版

链接:代码随想录

 

 看了题解,然后自己写出来了,一遍过啦啦啦啦啦

class Solution {
/*
呜呜呜好不容易送走了k=2次的,知道至少有2^2+1状态,
如若是k,难道要写2^k+1种状态吗?如果这么写,边界值k=100,2^100显然空间过于大了

这里想错了,j的范围就定义为 2 * k + 1。是线性的,因为对于第k次,有两个状态持有或者不持有。且奇数情况下固定初始值为-nums[0],偶数情况下固定初始值为0
即
dp[i][0] 不操作,初始值为0
dp[i][1]----第1次持有股票,初始值 -nums[0]
dp[i][2]----第1次不持有股票,初始值 0
dp[i][3]----第2次持有股票,初始值 -nums[0]
dp[i][4]----第2次不持有股票,初始值 0
.
.
.
dp[i][k]----第k次持有股票,初始值 -nums[0]
dp[i][2*k]----第2k次不持有股票,初始值 0



-----------------状态转移方程-------------------
dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i])

*/
public:
    int maxProfit(int k, vector<int>& prices) {
        int n=prices.size();
        if(n==0)
        {
            return 0;
        }
        vector<vector<int>>dp(n,vector<int>(2*k+1,0));
        
        //初始化i=0,即状态转移矩阵的第一行
        for(int j=0;j<2*k+1;j++)
        {
            if(j%2==1)//奇数,初始化
            {
              dp[0][j]=-prices[0];
            }
            else
            {
              dp[0][j]=0;
            }
        }
        //同时也默认初始化j=0第一列所有都等于0了
        //状态转移啦,因为第一行已经初始化过了,所以从第二行开始
        for(int i=1;i<n;i++)
        {
            for(int j=1;j<2*k+1;j++)
            {
                if(j%2==1)//奇数
                {
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]-prices[i]);
                }
                else
                {
                   dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+prices[i]); 
                }
            }
        }
        return dp[n-1][2*k];

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值