leetCode 122. The best time to buy and sell stocks II Dynamic programming + state transfer + state compression

122. The best time to buy and sell stocks II - LeetCode

You are given an array of integers  prices that  prices[i] represents the price of a certain stock on  i day 1.

On each day, you can decide whether to buy and/or sell stocks.  You can only hold  a maximum of one share at any 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) and sell on day 3 (stock price = 5) Out, the profit from this transaction = 5 - 1 = 4.
     Subsequently, if you buy on the 4th day (stock price = 3) and sell on the 5th day (stock price = 6), the profit from this transaction = 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), The profit from this transaction = 5 - 1 = 4.
     The total profit is 4.

Example 3:

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

The main difference between this question and leetCode 121. The best time to buy and sell stocks dynamic programming + state transfer is that it can be bought and sold multiple times.

>>Think and analyze

>>Five Steps of Dynamic Rules

1. Determine the meaning of dp array (dp table) and subscripts

  • dp[i][0] represents the maximum cash earned from holding stocks on day i
  • dp[i][1] represents the maximum cash earned by not holding stocks on day i

2. Determine the recursion formula

① If the stock is held on the i-th day, which is dp[i][0], then it can be deduced from the two states

  • If you hold the stock on day i - 1, then the status quo will be maintained. The cash earned from holding the stock yesterday is the cash earned now, that is :   
    • dp[i - 1][0]
  • If you buy stocks on day i, the cash you get after buying today’s stocks is your current income, that is :
    • In this question, because a stock can be bought and sold many times, when the stock is bought on the i-th day, the cash held may have profits from previous purchases and sales . Then the stock held on the i-th day is dp[i][0]. If the stock is purchased on the i-th day, the cash received is the cash received from not holding the stock yesterday minus today's stock price, that is :
      • dp[i - 1][1] - prices[i]

dp[i][0] should choose the one with the largest cash income, dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i] ) ;

② If you do not hold stocks on the i-th day, that is, dp[i][1], it can still be derived from the two states.

  • If you do not hold stocks on day i - 1, then the status quo will be maintained. The cash earned from not holding stocks yesterday is the current income.
    • dp[i-1][1]
  • The cash received from selling the stock on day i and selling it at today’s stock price is the current income, that is:                         
    • dp[i - 1][0] + prices[i]

dp[i][1] should choose the one with the largest cash income, dp[i][1] = max(dp[i - 1][1],dp[i - 1][0] + prices[i]);

3.dp array initialization

By the recursive formula

  • 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]);

The basis is to be derived from dp[0][0] and dp[0][1]

  • dp[0][0] -= prices[0];
  • dp[0][1] = 0;

4. Determine the traversal order

It can be seen from the recursion formula that  dp[i] is derived from dp[i - 1] , so it must be   traversed from front to back .

5. Derivation of dp array with examples

 

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        vector<vector<int>> dp(len, vector<int>(2, 0));
        dp[0][0] -= prices[0];
        dp[0][1] = 0;
        for (int i = 1; i < len; i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]); // 注意这里是和121. 买卖股票的最佳时机唯一不同的地方。
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
        }
        return dp[len - 1][1];
    }
};
  • Time complexity: O(n)
  • Space complexity: O(n)

 >>Optimize space complexity

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int len = prices.size();
        vector<vector<int>> dp(2, vector<int>(2)); // 注意这里只开辟了一个2 * 2大小的二维数组
        dp[0][0] -= prices[0];
        dp[0][1] = 0;
        for (int i = 1; i < len; i++) {
            dp[i % 2][0] = max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] - prices[i]);
            dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);
        }
        return dp[(len - 1) % 2][1];
    }
};
  • Time complexity: O(n)
  • Space complexity: O(1)

 >>Summary

This question is almost the same as the code of leetCode 121. The best time to buy and sell stocks . The only difference is :

dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);

This is precisely because the stocks in this question can be bought and sold multiple times!

Therefore, when buying stocks, there may be profits from previous transactions: dp[i - 1][1] , then

  • dp[i][0] = dp[i - 1][1] - prices[i]

Reference and recommended articles and videos

Code Random Record (programmercarl.com)

 Dynamic programming, the second round of stock problems | LeetCode: 122. The best time to buy and sell stocks II_bilibili_bilibili

Class screenshots from Code Caprice:

Guess you like

Origin blog.csdn.net/weixin_41987016/article/details/133432053