188. Best Time to Buy and Sell Stock IV(一个小结)

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most k transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.


AC代码:

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n=prices.size();
        if(n<=1)return 0;
        else if(k>n/2){
            int res=0;
            for(int i=1;i<n;i++)
                res+=max(prices[i]-prices[i-1],0);
            return res;
        }
        else{
            int tmp_max;
            vector<vector<int>>f(k+1,vector<int>(n,0));
            for(int i=1;i<=k;i++){
                tmp_max=-prices[0];
                for(int j=1;j<n;j++){
                    f[i][j]=max(f[i][j-1],tmp_max+prices[j]);
                    tmp_max=max(tmp_max,f[i-1][j]-prices[j]);
                }
            }
            return f[k][n-1];
        }
    }
};


以下来自Discuss:

Clearly DP is one of solutions to this kind of problems. I will like to summarize how to start and analyze for beginners:

Goal: find the max profit at day n-1 with at most k transactions.

Here we know we have two keys: day and transaction, of course it depends on past history (previous day with certain transactions), so if you try to solve this in a pure math. calculation and struggle with so many possibilities, that means we had better switch to consider how to build the math. model.

Notations:

f[k][i]: max profit up to day i (included) with at most k transactions (global optimal objective)
g[k][i]: max profit up to day i (included) with at most k transactions AND we sell at day i (local optimal objective, why local? think about it!)

DP recursive formula:
(1). f[k][i] = max ( f[k][i-1], g[k][i] )
(2). g[k][i] = max_{j=0,...,i-1} (p[i] - p[j] + f[k-1][j-1])
// (1): this means if we don't sell at day i, then f[k][i] is just f[k][i-1]; otherwise f[k][i] will be the max profit that we can achieve if we sell at day i
// (2): since we will sell at day i anyway, that means we need to buy at a certain previous day, for a particular j, the best we can have is p[i] - p[j] + f[k-1][j-1].

With these formulas, we can start to code by computing and storing all the information of f[k][i] and g[k][i]. One trick is that for (2), the max is easy to handle because we compute g[k][i] for i=0,1,2,... (with fixed k), so use one temp variable to keep updating the value will be enough.

If we think carefully, (1) and (2) only use the information on k-1, that means we can reduce the space complexity O(k*n) to O(n) pretty easily.

Can we reduce the space to be O(k)? The answer is yes. Of course, the formula (2) looks a bit ugly. Let's rewrite it a bit:
(2)'. g[k][i] = max ( g[k][i-1], f[k-1][i-1]) ) + p[i] - p[i-1].

Now let me put (1) and (2)' together:
(1). f[k][i] = max ( f[k][i-1], g[k][i] )
(2)'. g[k][i] = g[k][i-1], f[k-1][i-1]) + p[i] - p[i-1]
It's a lot simpler, right? The key is to get the current state (k,i), we only need the k-1 or i-1 information. So in the code, we have two loops but with outer: i-loop and inter: k-loop. This will makes space to be O(k). If k is way more small than n, then you can consider it's a good improvement.

You might come up (1) and (2)' directly, but here I just want to explain what happened in peterleetcode's post. So I start with his formulation. Finally, attach my code (may not be optimized) Whoops, this code is for IV, but should work for III case also.

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n=prices.size();
        if (n<2) return 0;
        if (k>=n/2) { // buy-sell-II case, unlimited
            int maxProfit=0;
            for (int i=1; i<n; ++i) {
                if (prices[i]>prices[i-1]) maxProfit += prices[i] - prices[i-1];
            }
            return maxProfit;
        }
        // if k<n/2, use DP approach but only O(k) space
        vector<int> f(k+1,0), g(k+1,0);
        for (int i=1; i<n; ++i) {
            int diff = prices[i] - prices[i-1], temp = f[0];
            for (int kk=1; kk<=k; ++kk) {
                g[kk] = max(g[kk], temp) + diff;
                temp=f[kk];
                f[kk] = max(f[kk], g[kk]);
            }
        }
        return f[k];
    }
};

PS: be careful in (2)', we have f[k-1][i-1], so before updating f[kk], we should save it for later use. Or I believe you can use different order of k to remove this "ugly" part.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值