LeetCode. Best Time to Buy Stock及其follow up II, III, IV

LeetCode 121 Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

解法:由于要返回数组里差值最大的,我们用iteration的方法,每次求得可能的最大差值后更新当前的最小值min即可,最后判断一下返回答案。代码如下:

    public int maxProfit(int[] prices) {
        int res = 0;
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < prices.length; i++) {
            res = Math.max(res, prices[i] - min);
            min = Math.min(min, prices[i]);
        }
        return res <= 0 ? 0 : res;
    }

LeetCode 122. Best Time to Buy and Sell Stock II

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 as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).

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

Example 1:

Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
             Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.
Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0

解法:由于可以完成多笔交易,并且一天可以同时卖出和买进,因此我们可以在只要有利可图的时候就买进和卖出即可,一个iteration搞定

    public int maxProfit(int[] prices) {
        int res = 0;
        for (int i = 0; i < prices.length - 1; i++) {
            if (prices[i] < prices[i+1]) {
                res += prices[i+1] - prices[i];
            }
        }
        return res;
    }

LeetCode 123. Best Time to Buy and Sell Stock III

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 two transactions.

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

Example 1:

Input: [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
             Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.
Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.
Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
分析:以下为讨论区里的一个高赞答,基本思路可以这么想,当我们iterate到第i个值时,可能的答案是:1、最终答案不包含当前值:答案便是遍历到i-1时的答案;2、最终答案包含当前值,证明交易需要修改,假设这笔新交易的买入点为j,则有j处买,i处卖,那么最终答案为此次新增的交易+之前的交易,(k-1)可能为0,也可能为1。(最终交易的k取值为三种可能:0,1,2)。

It’s not difficult to get the DP recursive formula:

dp[k, i] = max(dp[k, i-1], prices[i] - prices[j] + dp[k-1, j-1]), j=[0..i-1]

For k transactions, on i-th day,
if we don’t trade then the profit is same as previous day dp[k, i-1];
and if we bought the share on j-th day where j=[0…i-1], then sell the share on i-th day then the profit is prices[i] - prices[j] + dp[k-1, j-1] .
Actually j can be i as well. When j is i, the one more extra item prices[i] - prices[j] + dp[k-1, j] = dp[k-1, i] looks like we just lose one chance of transaction.

I see someone else use the formula dp[k, i] = max(dp[k, i-1], prices[i] - prices[j] + dp[k-1, j]), where the last one is dp[k-1, j] instead of dp[k-1, j-1]. It’s not the direct sense, as if the share was bought on j-th day, then the total profit of previous transactions should be done on (j-1)th day. However, the result based on that formula is also correct, because if the share was sold on j-th day and then bought again, it is the same if we didn’t trade on that day.

So the straigtforward implementation is:

    public int MaxProfitDp(int[] prices) {
        if (prices.Length == 0) return 0;
        var dp = new int[3, prices.Length];
        for (int k = 1; k <= 2; k++)  {
            for (int i = 1; i < prices.Length; i++) {
                int min = prices[0];
                for (int j = 1; j <= i; j++)
                    min = Math.Min(min, prices[j] - dp[k-1, j-1]);
                dp[k, i] = Math.Max(dp[k, i-1], prices[i] - min);
            }
        }

        return dp[2, prices.Length - 1];
    }

Time complexity is O(kn^2), space complexity is O(kn).
In the above code, min is repeated calculated. It can be easily improved as:

    public int MaxProfitDpCompact1(int[] prices) {
        if (prices.Length == 0) return 0;
        var dp = new int[3, prices.Length];
        for (int k = 1; k <= 2; k++) {
            int min = prices[0];
            for (int i = 1; i < prices.Length; i++) {
                min = Math.Min(min, prices[i] - dp[k-1, i-1]);
                dp[k, i] = Math.Max(dp[k, i-1], prices[i] - min);
            }
        }

        return dp[2, prices.Length - 1];
    }

Time complexity is O(kn), space complexity is O(kn).

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).

Example 1:

Input: [2,4,1], k = 2
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
Example 2:

Input: [3,2,6,5,0,3], k = 2
Output: 7

Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4.
Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.

分析:相对上一问,只需要把2换成k即可,为了防止k过大导致循环过多,我们可以剪枝:当k >= len/2,我们就可以在只要有利可图时就交易,就可以不用进入dp的循环。基本思想和前一问一样,只是多加一个剪枝优化。

    public int maxProfit(int kk, int[] prices) {
        if (prices.length == 0) return 0;
        if (kk >= prices.length / 2) return quickSolve(prices);
        int[][] dp = new int[kk+1][prices.length];
        for (int k = 1; k <= kk; k++) {
            int min = prices[0];
            for (int i = 1; i < prices.length; i++) {
                min = Math.min(min, prices[i] - dp[k-1][i-1]);
                dp[k][i] = Math.max(dp[k][i-1], prices[i] - min);
            }
        }

        return dp[kk][prices.length - 1];
    }
    private int quickSolve(int[] prices) {
        int len = prices.length, profit = 0;
        for (int i = 1; i < len; i++)
            // as long as there is a price gap, we gain a profit.
            if (prices[i] > prices[i - 1]) profit += prices[i] - prices[i - 1];
        return profit;
    }

猜你喜欢

转载自blog.csdn.net/katrina95/article/details/85316304
今日推荐