[Algorithm question] The best time to buy and sell stocks in the intermediate stage of dynamic programming, the minimum path of the triangle and

foreword

Dynamic programming (Dynamic Programming, DP for short) is a method to solve the optimization problem of multi-stage decision-making process. It is a strategy for decomposing complex problems into overlapping subproblems, and deriving the optimal solution to the problem by maintaining the optimal solution for each subproblem.

The main idea of ​​dynamic programming is to use the optimal solution of the solved sub-problem to derive the optimal solution of a larger problem, thus avoiding repeated calculations. Therefore, dynamic programming usually uses a bottom-up approach to solve small-scale problems first, and then gradually derive larger-scale problems until the optimal solution of the entire problem is solved.

Dynamic programming usually includes the following basic steps:

  1. Define the state: Divide the problem into several sub-problems, and define the state to represent the solution of the sub-problems;
  2. Define the state transition equation: According to the relationship between the sub-problems, design the state transition equation, that is, how to deduce the calculation process of the unknown state from the known state;
  3. Determine the initial state: define the solution of the smallest sub-problem;
  4. Bottom-up solution: Calculate the optimal solution of all states according to the state transition equation;
  5. Constructs the solution of the problem from the optimal solution.

Dynamic programming can solve many practical problems, such as shortest path problem, knapsack problem, longest common subsequence problem, edit distance problem, etc. At the same time, dynamic programming is also the core idea of ​​many other algorithms, such as divide and conquer algorithm, greedy algorithm, etc.

Dynamic programming is a method to solve the optimization problem of multi-stage decision-making process. It decomposes complex problems into overlapping sub-problems, and derives the optimal solution of the problem by maintaining the optimal solution of each sub-problem. Dynamic programming includes steps such as defining states, designing state transition equations, determining initial states, bottom-up solutions, and constructing problem solutions. Dynamic programming can solve many practical problems, and it is also one of the core ideas of other algorithms.

1. Triangular minimum path and

Given a triangle triangle, find the minimum path sum from top to bottom.

Each step can only move to the adjacent nodes in the next row. Adjacent nodes here refer to two nodes whose subscripts are the same as the subscript of the previous node or equal to the subscript of the previous node + 1. That is, if it is at subscript i of the current row, then the next step can move to subscript i or i+1 of the next row.

Example 1:

Input: triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
Output: 11
Explanation: As shown in the diagram below:
2
3 4
6 5 7
4 1 8 3
The top-down minimum path sum is 11 (ie, 2 + 3 + 5 + 1 = 11).

Example 2:

Input: triangle = [[-10]]
Output: -10

Source: LeetCode.

1.1. Ideas

Define a two-dimensional dp array, and change the "top-down recursion" in Solution 2 to "bottom-up recursion".

1. State definition: dp[i][j] represents the minimum path sum from point (i, j) to the edge.

2. State transition: dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+triangle[i][j] .

1.2. Code implementation

class Solution {
    
    
    public int minimumTotal(List<List<Integer>> triangle) {
    
    
        int n = triangle.size();
        // dp[i][j] 表示从点 (i, j) 到底边的最小路径和。
        int[][] dp = new int[n + 1][n + 1];
        // 从三角形的最后一行开始递推。
        for (int i = n - 1; i >= 0; i--) {
    
    
            for (int j = 0; j <= i; j++) {
    
    
                dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle.get(i).get(j);
            }
        }
        return dp[0][0];
    }
}

Time complexity: O ( N 2 ) O(N^2)O ( N2 ), N is the number of rows of the triangle.
Space Complexity:O ( N 2 ) O(N^2)O ( N2 ), N is the number of rows of the triangle.

2. The best time to buy and sell stocks II

You are given an integer array prices, where prices[i] represents the price of a certain stock on day i.

On each day, you can decide whether to buy and/or sell stocks. You can hold no more than one share of stock at any one time. You can also buy first and then sell on the same day.

Return the maximum profit you can make.

Example 1:

Input: prices = [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (stock price = 1), sell on day 3 (stock price = 5) Out, this transaction can make profit = 5 - 1 = 4.
Then, buy on the 4th day (stock price = 3) and sell on the 5th day (stock price = 6), this transaction can make profit = 6 - 3 = 3.
The total profit is 4 + 3 = 7.

Example 2:

Input: prices = [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (stock price = 1), sell on day 5 (stock price = 5), Profit = 5 - 1 = 4 for this trade.
The total profit is 4.

Example 3:

Input: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, the transaction cannot obtain a positive profit, so the maximum profit can be obtained by not participating in the transaction, and the maximum profit is 0.

Source: LeetCode.

2.1. Ideas

(1) Step 1: Define the state.
The state dp[i][j] is defined as follows:
dp[i][j] represents the maximum amount of cash we have on hand when the holding state is j on the day subscript i.

Note: The purpose of limiting the holding state to j is to facilitate the derivation of the state transition equation, which satisfies no aftereffect.

in:

  • The first dimension i represents the day with the subscript i (it has a prefix property, that is, the transactions of the previous days are considered);
  • The second dimension j indicates whether the subscript i holds stocks or cash on the day. Here 0 means holding cash (cash), and 1 means holding stocks (stock).

(2) Step 2: Think about the state transition equation
The state starts from holding cash (cash), and the state we care about on the last day is still holding cash (cash);
every day the state can be transferred or not. The state transition is represented by the following figure:
insert image description here
Description:

  • Since there is no limit to the number of transactions, except for the last day, the status of each day may not change or may be transferred;
  • When writing code, you don’t need to process the last day separately, just output the value when the status is 0 on the last day.

(3) Step 3: Determine the initial value
Initially:

  • If nothing is done, dp[0][0] = 0;
  • If you hold stocks, the amount of cash you currently have is the opposite of the stock price of the day, that is, dp[0][1] = -prices[i];

(4) Step 4: Determine the output value; at the time of termination, the above analysis also outputs dp[len - 1][0], because there must be dp[len - 1][0] > dp[len - 1] [1].

2.2. Code implementation

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

Time complexity: O(N), where N represents the length of the stock price array;
space complexity: O(N), although it is a two-dimensional array, the second dimension is a constant, which has nothing to do with the scale of the problem.

optimization:

class Solution {
    
    
public:
    int maxProfit(vector<int>& prices) {
    
    
        int n = prices.size();
        int dp0 = 0, dp1 = -prices[0];
        for (int i = 1; i < n; ++i) {
    
    
            int newDp0 = max(dp0, dp1 + prices[i]);
            int newDp1 = max(dp1, dp0 - prices[i]);
            dp0 = newDp0;
            dp1 = newDp1;
        }
        return dp0;
    }
};

Time complexity: O(N), where N represents the length of the stock price array;
space complexity: O(1).

Summarize

Dynamic programming (Dynamic Programming) is a method to solve multi-stage decision-making optimization problems. It decomposes complex problems into overlapping sub-problems and derives the optimal solution of the problem by maintaining the optimal solution of each sub-problem. Dynamic programming can solve many practical problems, such as shortest path problem, knapsack problem, longest common subsequence problem, edit distance problem, etc.

The basic idea of ​​dynamic programming is to use the optimal solution of the solved sub-problem to derive the optimal solution of a larger problem, thus avoiding repeated calculations. It usually uses a bottom-up approach to solve small-scale problems first, and then gradually derive larger-scale problems until the optimal solution of the entire problem is solved.

Dynamic programming usually includes the following basic steps:

  1. Define the state: Divide the problem into several sub-problems, and define the state to represent the solution of the sub-problems;
  2. Define the state transition equation: According to the relationship between the sub-problems, design the state transition equation, that is, how to deduce the calculation process of the unknown state from the known state;
  3. Determine the initial state: define the solution of the smallest sub-problem;
  4. Bottom-up solution: Calculate the optimal solution of all states according to the state transition equation;
  5. Constructs the solution of the problem from the optimal solution.

The time complexity of dynamic programming is usually O ( n 2 ) O(n^2)O ( n2 )orO(n3)O(n^3)O ( n3 ), the space complexity is O(n), where n represents the scale of the problem. In practical applications, in order to reduce space complexity, techniques such as rolling arrays can usually be used to optimize dynamic programming algorithms.

insert image description here

Guess you like

Origin blog.csdn.net/Long_xu/article/details/131484740