[difficult] best stock trading opportunity

Keywords: Algorithm Dynamic Programming

problem

Given an array arr of length N, its ith element is the price of a given stock on day i.
Design an algorithm to calculate the maximum profit you can make. You can complete up to k transactions.
You cannot participate in multiple transactions at the same time (you must sell the previous shares before buying again).

[dynamic planning ideas]

First, when k > = n / 2, this question can be the same as you can complete any transaction. The idea at this time is to grasp all growth ranges, that is, the demand.

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-fft4dfny-1631929396635) (EV) ernotecid://F1227914-1506-468F-92ED-DE7A9295E764/appyinxiangcom/27255310/ENResource/p281 )]

As shown in the figure, we can seize every opportunity to buy and sell, which is the optimal solution.
Then when k < n / 2, we need to discuss and dynamic programming.
A very easy idea, one sample as a row and one sample as a column model
At this time, for dp[i][j] day I, the maximum profit can be obtained by conducting J transactions.
In this sense, we try to deduce the dynamic transfer equation.

It is discussed by case. For dp[i][j] two cases
(1) Do not participate in selling on day i
(2) Participate in selling on day i
Result = max (case 1, case 2);
Case 1 is simply equivalent to dp[i-1][j]
Case 2: in this case, we may need to perform an enumeration and

dp[i][j] = MAX(
dp[i][j-1] + arr[i] - arr[i],
dp[i-1][j-1] + arr[i] - arr[i-1],
dp[i-2][j-1] + arr[i] - arr[i-2],
......
dp[0][j-1] + arr[i] - arr[0]
)

It seems that this is feasible. Its semantics is the maximum value of 0-i not sold before and sold at this time.
At this time, the most time-consuming is the enumeration behavior of [case 2]. Let's think about whether there are methods to optimize this enumeration behavior.
Look dp[i-1][j]:

dp[i-1][j] = MAX(
dp[i-1][j-1] + arr[i-1] - arr[i-1],
dp[i-2][j-1] + arr[i-1] - arr[i-2],
dp[i-3][j-1] + arr[i-1] - arr[i-3],
......
dp[0][j-1] + arr[i] - arr[0]
)

We extract the formula as follows:

dp[i][j] = MAX(
dp[i][j-1]  - arr[i],
dp[i-1][j-1] - arr[i-1],
dp[i-2][j-1]  - arr[i-2],
......
dp[0][j-1]  - arr[0]
) + arr[i]


dp[i-1][j] = MAX(
dp[i-1][j-1] - arr[i-1],
dp[i-2][j-1] - arr[i-2],
dp[i-3][j-1] - arr[i-3],
......
dp[0][j-1] - arr[0]
) + arr[i-1]

At this time, the enumeration calculation of [case 2] max is the maximum value of dp[i-1][j] case 2 that can rely on the previous optimal solution, so dp[i][j] can rely on this value and omit enumeration
Namely:

dp[i][j]= MAX(dp[i-1][j]Case 2 max ,dp[i][j-1] - arr[i]) + arr[i]

ok theory exists and put into practice

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/

Problem solution

package algorithmic.total.solution.common;

/**
 * @program: algorithmic-total-solution
 * @description: The best time to buy and sell stocks
 * Given an array arr of length N, its ith element is the price of a given stock on day i.
 * Design an algorithm to calculate the maximum profit you can make. You can complete up to k transactions.
 * You cannot participate in multiple transactions at the same time (you must sell the previous shares before buying again).
 * @author: wangzibin
 **/
public class Question4 {

    public static void main(String[] args) {
        int[] price=new int[]{9,3,4,9,5,1};
        System.out.println(getMaxProfit(price,2));
    }


    public static int getMaxProfit(int[] arr, int k) {
        if (arr == null || arr.length < 1) {
            return 0;
        }
        int length = arr.length;
        if (k >= length / 2) {
            return getMaxProfit(arr);
        } else {
            int[][] dp = new int[length][k + 1];

            for (int j = 1; j < k + 1; j++) {
                int preMax = dp[0][j-1]-arr[0];
                for (int i = 1; i < length; i++) {
                    preMax = Math.max(preMax, dp[i][j - 1] - arr[i]);
                    dp[i][j] = Math.max(preMax + arr[i], dp[i - 1][j]);
                }
            }
            return dp[length - 1][k];
        }
    }

    private static int getMaxProfit(int[] arr) {
        if (arr == null || arr.length < 1) {
            return 0;
        }
        int buy = 0;
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[buy] < arr[i]) {
                sum += arr[i] - arr[buy];
            }
            buy = i;
        }
        return sum;
    }

}


Posted by v0id on Sun, 19 Sep 2021 01:45:36 -0700