Code Caprice Day 49

1. The best time to buy and sell stocks:

greedy

Because the stock is only bought and sold once, the greedy idea is naturally to take the leftmost minimum value and the rightmost maximum value, then the difference obtained is the maximum profit.

The C++ code is as follows:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int low = INT_MAX;
        int result = 0;
        for (int i = 0; i < prices.size(); i++) {
            low = min(low, prices[i]);  // 取最左最小价格
            result = max(result, prices[i] - low); // 直接取最大区间利润
        }
        return result;
    }
};

Dynamic programming:

The analysis of the five parts of the dynamic regulation is as follows:

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

dp[i][0] means that holding the stock on the i-th day earns the most cash. Some students may have doubts here. This question can only be bought and sold once. How can there be cash after holding the stock?

In fact, the cash is 0 at the beginning, so adding the cash to buy stocks on the i-th day is -prices[i], which is a negative number.

dp[i][1] means the maximum amount of cash obtained by not holding stocks on the i-th day

Note that "hold" is mentioned here, and "hold" does not mean "buy" on the same day! It is also possible that I bought it yesterday and kept it today

Many students do not clearly distinguish between "holding" and "buying".

In the analysis of the recursive formula below, I will explain further.

     2. Determine the recursive formula

If you hold the stock on the i-th day, that is, dp[i][0], then it can be deduced from two states

  • Hold the stock on the i-1 day, then keep the status quo, and the cash you get is the cash you got from holding the stock yesterday, that is: dp[i - 1][0]
  • Buying stocks on the i-th day, the cash you get is the cash you get after buying today’s stocks: -prices[i]

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

Here dp[i][0] are all negative, so the bigger the better (that is, the closer to 0), so that the cost of buying stocks is small. In fact, it is looking for the stock with the lowest cost, but it is the cash obtained, so it is negative, so it becomes the largest

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

  • If you don’t hold stocks on day i-1, then keep the status quo, and the cash you get is the cash you got from not holding stocks yesterday, that is: dp[i - 1][1]
  • Sell ​​the stock on the i-th day, and the cash you get is the cash you get after selling the stock at today's stock price: prices[i] + dp[i - 1][0]

Similarly dp[i][1] takes the largest, dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);

Here is the profit, the bigger the better.

In this way, we have finished analyzing the recursive formula.

      3. How to initialize the dp array

By the recursive formula dp[i][0] = max(dp[i - 1][0], -prices[i]); and dp[i][1] = max(dp[i - 1][1 ], prices[i] + dp[i - 1][0]); It can be seen that

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

Then dp[0][0] means holding stocks on the 0th day, and holding stocks at this time must be buying stocks, because it is impossible to launch them the day before, so dp[0][0] -= prices [0];

dp[0][1] means that no stock is held on the 0th day, and the cash is 0 if no stock is held, so dp[0][1] = 0;

      4. Determine the traversal order

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

      5. Example derivation dp array

Take Example 1, input: [7,1,5,3,6,4] as an example, the state of the dp array is as follows:

In fact, I have another way of thinking. For example, the dp array is exactly the same as his (except that the table is horizontal, and an absolute value is added to dp[i][0]):

An example corresponding to the problem solution The dp array dp[i][0] is the minimum value of the stock, and dp[i][1] is the maximum profit. (I feel the same way as greedy)

dp[5][1] is the final result.

Why not dp[5][0]?

Because in this question, you will get more money if you don’t hold stocks than if you hold stocks!

After the above analysis, the C++ code is as follows:

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

 There is also a way to write a scrolling array:

// 版本二
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], -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];
    }
};

2. The best time to buy and sell stocks II

First of all, make it clear that if you bought a stock earlier, that stock can be sold on the same day and bought on that day:

The maximum profit of [1,2,3] is 2 not 1.

So just add up the positive profit from day 2 to get the maximum.

It is almost exactly the same as the best time to buy and sell stocks I, but there is a little difference in the recursive formula:

Because it can buy and sell stocks many times, so when he buys stocks on day i, the recursive formula is dp[i - 1][1] - prices[i], and the original recursive formula is -prices[i] , because he just buys and sells once to find the maximum difference, and here is to add up the daily positive profits, so the previous profits that have been earned must be added.

The meaning of the dp array:

  • dp[i][0] represents the cash received from holding stocks on the i-th day.
  • dp[i][1] means the maximum amount of cash obtained by not holding stocks on the i-th day

If you hold the stock on the i-th day, that is, dp[i][0], then it can be deduced from two states

  • Hold the stock on the i-1 day, then keep the status quo, and the cash you get is the cash you got from holding the stock yesterday, that is: dp[i - 1][0]
  • Buying stocks on the i-th day, the cash obtained is the cash obtained from not holding stocks yesterday minus today’s stock price: dp[i - 1][1] - prices[i]

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

  • If you don’t hold stocks on day i-1, then keep the status quo, and the cash you get is the cash you got from not holding stocks yesterday, that is: dp[i - 1][1]
  • Sell ​​the stock on the i-th day, and the cash you get is the cash you get after selling the stock at today's stock price: prices[i] + dp[i - 1][0]

Note that this is the same logic as 121. The best time to buy and sell stocks (opens new window) . Selling stocks to reap profits (possibly negative values) is only right and proper!

Why is the sum of positive profits and the profit of selling stocks negative?

In fact, there is a bit of doubt here, especially after reading the idea of ​​​​greedy, seeking the sum of positive profits, but in fact, there is no need to worry, because

He calculated whether the current stock is bigger or smaller than the previous one: prices[i] + dp[i - 1][0], but this will not happen at all because before there is no positive profit, it is negative When making a profit, the initialized 0 is greater than the negative profit, so the profit is still 0 until a positive profit appears. After the positive profit appears, it is the comparison between the two max(dp[i-1][1],dp[i-1][0]+prices[i]), do not compare the previous dp[i-1][ 1] is written as 0, otherwise once there is a positive profit, it will be dp[i-1][0]+prices[i].

The writing method of scrolling array:

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];
    }
};

 

Guess you like

Origin blog.csdn.net/2201_75793783/article/details/130955927