# [leetcode 121] PHP three ways to solve the best time to buy and sell stocks

Time：2020-9-29

Link to the original text: he Xiaodong’s blog

##### The best time to buy and sell stocks

Given an array, its I th element is the price of a given stock on day I.

If you are allowed to complete at most one transaction (that is, to buy and sell a stock once), design an algorithm to calculate the maximum profit you can make.

Note: you can’t sell stocks before you buy them.

Example 1:

``````Input: [7,1,5,3,6,4]
Output: 5
Explanation: buy on day 2 (stock price = 1) and sell on day 5 (stock price = 6), with maximum profit = 6-1 = 5.
Note that the profit cannot be 7-1 = 6, because the selling price needs to be greater than the buying price; at the same time, you can't sell the stock before you buy it.``````

Example 2:

``````Input: [7,6,4,3,1]
Output: 0
Explanation: in this case, the transaction is not completed, so the maximum profit is 0.``````

Source: leetcode

##### Solutions 1 – exhaustive

Enumerate the difference between two adjacent elements and solve the problem violently.

As a result, it will time out when there is a large amount of data, and there are too many factorials.

##### code
``````class Solution {

/**
* @param Integer[] \$prices
* @return Integer
*/
function maxProfit(\$prices) {
\$count = count(\$prices);
if (\$count < 2) {
return 0;
}

//It is possible not to trade, so the initial value of the result is set to 0
\$res = 0;
for (\$i = 0; \$i < \$count - 1; \$i++) {
for (\$j = \$i + 1; \$j < \$count; \$j++) {
\$res = max(\$res, \$prices[\$j] - \$prices[\$i]);
}
}
return \$res;
}
}``````
##### The best edition

Record the minimum value in advance, and omit the inner loop.

``````class Solution {

/**
* @param Integer[] \$prices
* @return Integer
*/
function maxProfit(\$prices) {
\$count = count(\$prices);
if (\$count < 2) {
return 0;
}

\$res = 0;

//Represents the minimum value before the current position
\$minVal = \$prices[0];
//Note: this starts with 1
for (\$i = 1; \$i < \$count; \$i++) {
\$res = max(\$res, \$prices[\$i] - \$minVal);
\$minVal = min(\$minVal, \$prices[\$i]);
}
return \$res;
}
}``````
##### Solution 2 – dynamic programming

Set status`dp[i][j]`On the day of index I, the maximum profit obtained when the user’s holding status is J

J has only two values: 0 means no holding (especially refers to the non holding state after selling the shares), and 1 is the holding shares

The state transition equation is as follows

`dp[i][0]`How to transfer?

• `dp[i - 1][0]`Of course, it can be transferred from yesterday without holding shares, which means that nothing will be operated from yesterday to today
• `dp[i - 1][1] + prices[i]`Yesterday, I sold the stock on the day of index I, and the status changed from 1 to 0. At this time, I sold the stock, so I added the stock price of that day

To sum up:`dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])`;

How does DPI transfer?

• `dp[i - 1][1]`: yesterday’s shareholding, today’s nothing operation, of course, can be transferred from yesterday’s shareholding
• `-prices[i]`Note: status 1 cannot be derived from status 0, because in fact, status 0 specifically refers to “the state of not holding shares after selling stocks”, and the title can only be traded once, so it cannot be added`dp[i - 1][0]`

So,`-prices[i]`That is, on the day the index is I, the proceeds from the buy operation
To sum up:`dp[i][1] = max(dp[i - 1][1], -prices[i])`;

Initial value:

No shares on day 0, obviously`dp[0][0] = 0`
Day 0, obviously`dp[0][1] = -prices[0]`

##### code
``````class Solution {

/**
* @param Integer[] \$prices
* @return Integer
*/
function maxProfit(\$prices) {
\$count = count(\$prices);
if (\$count < 2) {
return 0;
}

\$res = 0;

//0: the maximum profit that users can get if they don't hold shares in their hands, especially when they sell stocks
//1: the maximum profit that users can get by holding shares in their hands

//Note: because the title can only be traded once, the status can only be from 1 to 0, not from 0 to 1
\$dp = [];
\$dp[0][0] = 0;
\$dp[0][1] = -\$prices[0];
for (\$i = 1; \$i < \$count; \$i++) {
\$dp[\$i][0] = max(\$dp[\$i - 1][0], \$dp[\$i - 1][1] + \$prices[\$i]);
\$dp[\$i][1] = max(\$dp[\$i - 1][1], -\$prices[\$i]);
}
return \$dp[\$count - 1][0];

//One dimensional array optimization
// \$dp = [];
// \$dp[0] = 0;
// \$dp[1] = -\$prices[0];
// for (\$i = 1; \$i < \$count; \$i++) {
//     \$dp[0] = max(\$dp[0], \$dp[1] + \$prices[\$i]);
//     \$dp[1] = max(\$dp[1], -\$prices[\$i]);
// }
// return \$dp[0];
}
}``````
##### Solution 3 – differential array

Differential arrayThe value of the sum of the successive subintervals of the original stock price array is exactly the price difference of the original stock price array for one transaction (back front)

For example: for arrays`1 6 2 8`, represents the daily price of the stock

Define a conversion rule. The price of the current day minus the price of the previous day. Since there is no previous day on the first day, it is specified as 0 to represent no operation

The array is converted to`0 6-1 2-6 8-2`That is to say`0 5 -4 6`。 Now the meaning of the array is the change of the stock relative to the previous day

Now we just need to find out what the continuous sum is, that is to say, 53 questions

Continuous sum, such as the sum of the corresponding day 3 to day 6, the corresponding buy and sell is actually the second day of buying and the sixth day of selling

Therefore, we can find the sum of the largest continuous subsequences on the difference group

##### code
``````class Solution {

/**
* @param Integer[] \$prices
* @return Integer
*/
function maxProfit(\$prices) {
\$count = count(\$prices);
if (\$count < 2) {
return 0;
}

\$dp = 0;
\$max = 0;
for (\$i = 1; \$i < \$count; \$i++) {
//Cumulative earnings on adjacent dates (difference)
\$num = \$prices[\$i] - \$prices[\$i - 1];
\$dp = max(\$dp + \$num, \$num);
\$max = max(\$max, \$dp);
}

return \$max;
}
}``````