【LeetCode刷题(困难程度)】188. 买卖股票的最佳时机 IV

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [2,4,1], k = 2
输出: 2
解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例 2:

输入: [3,2,6,5,0,3], k = 2
输出: 7
解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:本题需要用到的一些点和前面122. 买卖股票的最佳时机 II以及123. 买卖股票的最佳时机 III有一些共性的地方。
假设Nprice数组的大小。
那么首先第一个trick的地方在于,如果k > N/2,那么我们可以直接转化为122. 买卖股票的最佳时机 II,为什么呢?
因为我们即便全都是今天买,明天卖,那么最多可以买卖的次数为N / 2的下整次,这里可以自己举个栗子说明,即k如果大于N/2,那么多出来的那些次数完全是今天买今天卖的无用功。所以也可以等效为买卖无限多次了。即退化为122. 买卖股票的最佳时机 II

再来看k<=N/2的情况:
参考123. 买卖股票的最佳时机 III的分析情况,我们可以得到买卖过程中会出现的阶段有如下情况:
在这里插入图片描述
即我们的阶段从5增长到了2k+1次,所以我们把123题中的5改为2k+1就行了。
分析的过程是一样的。

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n = prices.size();
        if(n == 0)
            return 0;
        
        if(k > n/2)
        {
            //这里就退化成了可以买卖任意多次
            int sum = 0;
            for(int i = 0;i < n-1;++i)
            {
                if(prices[i+1] > prices[i])//只要后面一天的价格大于前一天的价格
                    sum += prices[i + 1] - prices[i];
            }
            return sum;  
        }
        vector<vector<int>>f(n+1,vector<int>(2*k+2,0));

        //初始化 f[i][j]表示在前i天中处于阶段j的最大获利
        f[0][1] = 0;
        for(int j = 2;j <= 2*k+1;++j)
        {
            f[0][j] = INT_MIN;
        }
        for(int i = 1;i<=n;++i)
        {
            //阶段1,3,5...2*k+1
            for(int j = 1;j<=2*k+1;j+=2)
            {
                f[i][j] = f[i-1][j];
                if(j > 1&& i>=2&&f[i-1][j-1]!=INT_MIN)
                {
                    f[i][j] = max(f[i][j],f[i-1][j-1] + prices[i-1] - prices[i-2]);
                }
            }

            //阶段2,4...2k
            for(int j = 2;j<=2*k+1;j+=2)
            {
                f[i][j] = f[i-1][j-1];
                if(i>=2&&f[i-1][j]!=INT_MIN)
                {
                    f[i][j] = max(f[i][j],f[i-1][j]+prices[i-1]-prices[i-2]);
                }
            }
        }
        int res = INT_MIN;
        for(int i = 1;i<=2*k+1;i+=2)
        {
            res = max(res,f[n][i]);
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_33197518/article/details/108984288