【C++编程能力提升】

代码随想录训练营Day50 | Leetcode 123、188

  • 一、123 买卖股票的最佳时机III
  • 二、188 买卖股票的最佳时机IV

一、123 买卖股票的最佳时机III

题目链接:123 买卖股票的最佳时机III

核心:限定了最多交易的次数是2,那么每个元素最多可存在的状态有4个:第一次持有&不持有,第二次持有&不持有(由于无需处理的状态均为0,故该状态可忽略),针对这四个不同状态求解其递推公式,然后遍历数组各元素得到各元素4个状态的dp数组。
第一,dp[i][0]:第i天第一次持有股票所得的现金,要么第i-1天已持有股票,要么第i天买入,且是第一次买入;
第二,dp[i][1]:第i天第一次不持有股票所得的现金,要么第i-1天已不持有股票,要么第i天卖出(隐含第i-1天是持有的);
第三,dp[i][2]:第i天第二次持有股票所得的现金,要么第i-1天已经第二次持有,要么第i天第二次买入(隐含第i-1天已经第一次不持有);
第四,dp[i][3]:第i天第二次不持有股票所得的现金,要么第i-1天已不持有,要么第i天卖出(第i-1天是第二次持有股票)。

    int maxProfit(vector<int>& prices) {
       //动态规划:限定最多2次,因此每个元素可能有4种状态:第一次持有/不持有,第二次持有/不持有
        int len=prices.size();
        if(len==0)  return 0;
        vector<vector<int>> dp(len,vector<int>(4)); //也可以增加一个不处理的状态
        dp[0][0]=-prices[0];  //第一次持有(存在买入)
        dp[0][1]=0;             //第一次不持有(存在卖出)
        dp[0][2]=-prices[0];    //第二次持有(第一个元素已经被买卖一次)(存在买入)
        dp[0][3]=0;             //第二次不持有(存在卖出)
        for(int i=1;i<len;++i)
        {
            dp[i][0]=max(dp[i-1][0],-prices[i]);    //要么i-1天已持有,要么i天买入
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]); //要么i-1天已不持有,要么i天卖出
            dp[i][2]=max(dp[i-1][2],dp[i-1][1]-prices[i]); //i天第二次买入时i-1天必然是第一次不持有的状态,否则第一次持有时不能买入
            dp[i][3]=max(dp[i-1][3],dp[i-1][2]+prices[i]); //第i天第二次卖出时i-1天必然是持有
        }
        return dp[len-1][3];    //最终利润最大值一定是第二次不持有的状态
    }

二、188 买卖股票的最佳时机IV

题目链接:188 买卖股票的最佳时机IV

核心:最多交易的次数增加到k次,那么每个元素可存在的状态有2k个,再加上一个无需处理的状态(dp[i][0]),一共有2k+1个状态,可定义一个列数维度为2*k+1的数组。
令奇数为第j次持有股票所得的现金,比如:dp[i][1],dp[i][3]等,则偶数就是相对应的第j次不持有股票所得的现金。
第一,奇数时(持有股票),要么第i-1天已持有,要么第i天买入;
第二,偶数时(不持有股票),要么第i-1天已不持有,要么第i天卖出。

    int maxProfit(int k, vector<int>& prices) {
        //动态规划,由于交易最多是k次,那么可能存在2*k次不同状态,另加上一个无需处理的状态
        int len=prices.size();
        if(len==0)  return 0;
        vector<vector<int>> dp(len,vector<int>(2*k+1,0));
        for(int j=1;j<2*k+1;j+=2)
            dp[0][j]=-prices[0];    //奇数表示第j次持有(存在买入)
        for(int i=1;i<len;++i)
        {//遍历元素
            for(int j=0;j<2*k-1;j+=2)
            {//遍历交易的第j次
                dp[i][j+1]=max(dp[i-1][j+1],dp[i-1][j]-prices[i]);  //奇数(持有),买入
                dp[i][j+2]=max(dp[i-1][j+2],dp[i-1][j+1]+prices[i]); //偶数(不持有),卖出
            }
        }
        return dp[len-1][2*k];
    }

你可能感兴趣的:(C++编程,c++,leetcode,动态规划)