Dynamic Programming on Intervals III (LeetCode #188)

LeetCode 188. Best Time to Buy and Sell Stock IV

You are given an integer array prices where prices[i] is the price of a given stock on the ith day, and an integer k.

Find the maximum profit you can achieve. You may complete at most k transactions.

Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).

Similar to its predecessors, we have to find the maximum profit given an array of stock prices. However, this time it is upgraded by giving you a maximum number of transactions. So following my previous method, I created a 3D integer array dp[i][j][k], indicating the maximum profit attainable from the i-th to j-th index given k transactions. We will calculate the transfer of state by finding the maximum of the sum of the first transaction from i-th to l-th index and the maximum value from l-th to the j-th index given k-1 transactions

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if(prices.size() <= 1)
            return 0;
        int dp[prices.size() + 1][prices.size() + 1][k+1];
        memset(dp, 0, sizeof(dp));
        // loop through number of transactions
        for(int a = 1; a <=k; a++){
            // loop through starting index
            for(int i = prices.size() - 1; i > 0; i--){
                int minx = prices[i-1];
                // loop through ending index
                for(int j = i + 1; j <= prices.size(); j++){
                    if(a > 1){
                        dp[i][j][a] = dp[i][j][a-1];
                        // loop through middle point
                        for(int l = i + 1; l < j; l++){
                            dp[i][j][a] = max(dp[i][j][a], 
                            dp[i][l][1] + dp[l][j][a-1]);
                        }
                    }else{
                        minx = min(minx, prices[j-1])
                        dp[i][j][a] = max(dp[i][j-1][a], prices[j-1] - minx);
                    }
                }
            }
        }
        return dp[1][prices.size()][k];
    }
};

 However, as you can see, our 3D array requires an enormous amount of storage. Given the input constraints of a maximum of 1000 elements and 100 transactions, that would require a maximum of 100million elements in our storage, which is impossible. Even if replaced with vectors, which supports a larger size, we are still going to get a TLE...


So, I changed the approach a little bit. Instead of a 3-D array, I am now using one with 1 less dimension. dp[i][j] means doing transactions starting from i-th index up to the end of the array. The transfer of state would still be similar to the one above. As for how we are going to calculate the maximum profit in the left array, i.e. the first transaction. we are simply going to do it in our old-fashioned way, by finding its minimum and finding the maximum difference in that part.

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        if(prices.size() <= 1)
            return 0;
        int dp[prices.size()][k+1];
        memset(dp, 0, sizeof(dp));
        int m;

        // loop through the number of transactions
        for(int a = 1; a <= k; a++){
            // loop through the starting index
            for(int i = 0; i < prices.size() - 1; i++){
                m = prices[i];
                // loop through the middle point
                for(int j = i + 1; j < prices.size(); j++){
                    dp[i][a] = max(dp[i][a], prices[j] - m + dp[j][a-1]);
                    m = min(m, prices[j]);
                }
            }
        }
        return dp[0][k];
    }
};

Note that we are doing some preprocessing in the first part. Since when k = 1, it is just a simple version of the stock question. The old way would suffice.


P.S. Though my implementation is pretty slow (only faster than 5%...), I got a pass in my first trial for my second implementation :)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值