Best Time to Buy and Sell Stock IV(动态规划)

题意:有一支股票每天的价格波动,请在给定的时间内完成k次交易使收益最大,一次交易代表买入再卖出,交易不能重叠(必须卖完之后在买)。

题解:我们首先设global[i][j]为到第i天为止交易j次的最大收益。
因为最后一次交易要么在第i天卖出,要么在之前卖出。在之前卖出的最大收益显然是global[i-1][j],而要求第i天卖出的最大收益我们需要枚举在前面哪一天买进。可以得到转移方程:
global[i][j] = max{global[i-1][j], max{global[k][j-1]+p[i]-p[k], 0<=k<=i}};
以上我们将k=i单独取出来则可以化简为:
global[i][j] = max{global[i-1][j], global[i][j-1], max{global[k][j-1]+p[i]-p[k], 0<=k<=i-1}};
以上为N^2*k的复杂度。
但是我们仔细观察最后一个max式子可以发现这个有明显的递推关系。它的意义在于仅在第i天卖出的最大收益。
则我们以空间换时间,再新建一个数组local[i][j]代表前i天交易j次,且第j次交易必须在第i天卖出的最大收益。
则有转移方程:
local[i][j] = max{global[k][j-1]+p[i]-p[k], 0<=k<=i},我们将p[i]-p[k] = p[i]-p[i-1]+p[i-1]-p[k]。

local[i][j] = max{global[k][j-1]+p[i-1]-p[k], 0<=k<=i}+p[i]-p[i-1],
再进一步
local[i][j] = max{global[i][j-1], max{global[k][j-1]+p[i-1]-p[k], 0<=k<=i-1}+p[i]-p[i-1]},
其中,max{global[k][j-1]+p[i-1]-p[k], 0<=k<=i-1}就是local[i-1][j]。
则有最终的转移方程:
local[i][j] = max{global[i][j-1], local[i-1][j]+p[i]-p[i-1]}
global[i][j] = max{global[i-1][j], local[i][j]}
具体实现时可以使用滚动数组节省空间。

代码如下:

class Solution {
public:
    int quickSolve(vector<int>& prices) {
        int maxProfit = 0;
        for(int i = 1;i < prices.size();i++) {
            if(prices[i] > prices[i-1]) {
                maxProfit += prices[i]-prices[i-1];
            }
        }
        return maxProfit;
    }

    int maxProfit(int k, vector<int>& prices) {
        int pSize = prices.size();
        if(k >= pSize/2) {
            //相当于可以进行无限次交易
            return quickSolve(prices);
        }
        vector<int> local(k+1, 0);
        vector<int> global(k+1, 0);
        for(int i = 1;i < pSize;i++) {
            int diff = prices[i]-prices[i-1];
            for(int j = 1;j <= k;j++) {
                local[j] = max(global[j-1], local[j]+diff);
                global[j] = max(global[j], local[j]);
            }
        }
        return global[k];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值