【LeetCode】Dynamic programming training (6)

123. Best Time to Buy and Sell Stocks III

Click to view: Best Time to Buy and Sell Stocks III


Given an array whose 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 two transactions.
Note: You cannot participate in multiple transactions at the same time (you must sell the previous stock before buying again).

Example 1:
Input: prices = [3,3,5,0,0,3,1,4]
Output: 6
Explanation: buy on day 4 (stock price = 0), buy on day 6 (stock Sell ​​when the price = 3), this transaction can make a profit = 3-0 = 3.
Then, buying on the 7th day (stock price = 1) and selling on the 8th day (stock price = 4), this transaction can make a profit = 4-1 = 3.
Example 2:
Input: prices = [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (stock price = 1), buy on day 5 (stock price = 5) Selling, this transaction can make a profit = 5-1 = 4.
Note that you cannot buy shares on Day 1 and Day 2 back-to-back and sell them later.
Because this is involved in multiple transactions at the same time, you must sell the previous shares before buying again.

topic analysis

Compared with the previous stock issue, except for the handling fee and freezing period, most of the others are the same,
but the number of transactions can be changed from one to two (up to two, or one or zero)

From buying stocks to selling stocks, it is considered to complete a transaction


zero transaction

Since the prices are in descending order, no matter when you buy stocks, you will lose money when you sell them.
Therefore, during this period, if you do nothing, the profit at this time is: 0 and
zero transactions are completed at this time

A deal

When the price is in ascending order, sell the stock on the first day, do nothing until the price is 5,
sell the stock when the price is 5, and the profit at this time is: 5-1=4
Complete a transaction at this time trade


two transactions

If you buy stocks on the first day, there will be no profit if you buy them on the second day, so you don’t do anything on the second day. On the third day
, you sell the stocks. The profit at this time is: 5-3=2


Buy the stock on the fourth day, and stay in a state of doing nothing until the price is 4 yuan.
When the price is 4 yuan, sell the stock.
The profit at this time is: 4-0=4
The sum of the two transactions completed The profit is: 4+2=6

Complete two transactions at this time

state transition equation

dp[i]: indicates the maximum profit that can be obtained after the end of the i-th day


At position i, there are two states, buying state and selling state.
Use f to represent the buying state, and g to represent the selling state.
i represents the end of day i
and j represents the number of transactions

f[i][j]: means that after the end of the i-th day, j transactions have been completed, and the maximum profit at this time is g[i][j]: means that since the end of the i-th day, the transaction has been
completed j transactions, in the selling state, the maximum profit at this time

After completing the operation of buying stocks and selling stocks, the number of transactions will be changed


f[i][j] state transition equation

If the i-1th day is in the buying state, then do nothing on the i-th day, and the i-th day is also in the buying state
In this case: f[i][j]=f[i-1][j];


If the i-1th day is in the selling state, then the i-th day is in the buying state.
You need to subtract the price[i] corresponding to buying the stock.
In this case: f[i][j]=g[i-1][ j]-price[i];


The state transition equation is:
f[i][j]=max(f[i-1][j],g[i-1][j]-price[i]);

g[i][j] state transition equation

If the i-1th day is in the selling state, then do nothing on the i-th day, then the i-th day is also in the selling state
In this case: g[i][j]=g[i-1][j] ;


If the i-1th day is in the buying state, then the i-th day is in the selling state. The
profit price[i] corresponding to selling stocks needs to be added,
because the state from buying to selling is completed, the number of transactions on the i-th day +1 becomes j. At this time, j is +1 on the original number of times
and the number of transactions on the i-1th day is still the original number of times. Therefore, it should be j-1
from buying stocks to selling stocks. Calculate the completion of a transaction
assuming that j is 0, then buy stocks on the i-1th day, the number of transactions is 0
and sell stocks on the i-th day, the number of transactions is 1

In this case: g[i][j]=f[i-1][j-1]+price[i];


The state transition equation is:
g[i][j]= max(g[i-1][j],f[i-1][j-1]+price[i]);

initialization

For the state transition equation of g[i][j], when j is 0, -1 transaction is completed on the i-1 day, this situation does not exist, so the state of g[i][j] can
be The transfer equation is modified


In the first step, assign g[i][j] to g[i-1][j], so directly replace g[i-1][j] with g[i][j in the if loop ]
In this way, -1 transactions can be avoided


The ordinate indicates that after the end of the i-th day,
the abscissa indicates the completion of the i transaction
. When the ordinate is 0, it means that 0/1/2 transactions are completed after the end of the 0th day. This situation does not exist. Buying
and selling on the same day , there is no profit, and the number of transactions is limited,
so in order not to interfere with the subsequent results, after the end of the 0th day, when 1/2 transactions are completed, they are all set to negative infinity


f[0][0]: Indicates that after the end of the 0th day, it is in the buying state, that is, buying the stock will cost money, and the profit will be negative
f[0][0]=-price[0];


g[0][0]: Indicates that after the end of the 0th day, it is in a selling state (after the end of the 0th day, there is no stock in hand, and it cannot be sold, which is equivalent to doing nothing, and the profit is 0) g[
0 ][0]=0;


If you select INT_MIN for negative infinity, an
out-of-bounds problem will occur Negative infinity selection -0x3f3f3f3f(0x3f3f3f3f is half of the maximum value of int)

full code

class Solution {
    
    
public:
    int maxProfit(vector<int>& prices) {
    
    
       int n=prices.size();
       //因为可能完成 0 1 2 三笔交易其中一种 所以定义为3列
       //负无穷大 若要设置为INT_MIN会发生越界问题
       //所以使用 -0x3f3f3f
       vector<vector<int>>f(n,vector<int>(3,-0x3f3f3f3f));
       vector<vector<int>>g(n,vector<int>(3,-0x3f3f3f3f));
       int i=0;
       int j=0;
       //初始化
       f[0][0]=-prices[0];
       g[0][0]=0;
       for(i=1;i<n;i++)
       {
    
    
           for(j=0;j<3;j++)
           {
    
    
               f[i][j]=max(f[i-1][j],g[i-1][j]-prices[i]);
               //修改后的状态转移方程 
               g[i][j]=g[i-1][j];
               if(j-1>=0)
               {
    
    
                   g[i][j]=max(g[i][j],f[i-1][j-1]+prices[i]);
               }
           }
       }
       int ret=INT_MIN;
        //寻找最后一行g的最大值
        for(j=0;j<3;j++)
        {
    
    
            if(ret<g[n-1][j])
            {
    
    
                 ret=g[n-1][j];
            }
        }
        //返回最后一行g的最大值
        return ret;
    }
};

Return value
Since the maximum profit may be 0 transactions/1 transaction/2 transactions
If f is used, it means that it has reached the last position and is still in the buying state, so it cannot be the maximum profit,
so use g and count the last of g The maximum value of a row (0,1,2 position)

188. Best Time to Buy and Sell Stocks IV

Click to view: Best Time to Buy and Sell Stocks IV


Given an integer array prices, its i-th element prices[i] is the price of a given stock on day i, and an integer k.
Design an algorithm to calculate the maximum profit you can make. You can complete at most k transactions. In other words, you can buy k times at most and sell k times at most.
Note: You cannot participate in multiple transactions at the same time (you must sell the previous stock before buying again).

Example 1:
Input: k = 2, prices = [2,4,1]
Output: 2
Explanation: buy on day 1 (stock price = 2), buy on day 2 (stock price = 4) Selling, this transaction can make a profit = 4-2 = 2.
Example 2:
Input: k = 2, prices = [3,2,6,5,0,3]
Output: 7
Explanation: buy on day 2 (stock price = 2), buy on day 3 (stock Sell ​​when price = 6), this transaction can make profit = 6-2 = 4.
Then, buy on the 5th day (stock price = 0) and sell on the 6th day (stock price = 3), this transaction can make profit = 3-0 = 3.

topic analysis

This question is basically similar to the best time to buy and sell stocks III, except that the previous maximum of 2 times (0 1 2 three possibilities) has been changed to k times ([0,k-1] possibilities


k is 2, which means at most 2 transactions (0 transaction/1 transaction/2 transactions are three possibilities) to seek the maximum profit


Buy stocks on the first day and sell them on the second day, the profit at this time is: 4-2=2
The third day is the last day, so do nothing,
that is, the maximum profit is: 2

state transition equation

(The best timing IV question is basically the same as the best timing III in the analysis stage)


dp[i]: indicates the maximum profit that can be obtained after the end of the i-th day

At position i, there are two states, buying state and selling state.
Use f to represent the buying state, and g to represent the selling state.
i represents the end of day i
and j represents the number of transactions

f[i][j]: means that after the end of the i-th day, j transactions have been completed, and the maximum profit at this time is g[i][j]: means that since the end of the i-th day, the transaction has been
completed j transactions, in the selling state, the maximum profit at this time

After completing the operation of buying stocks and selling stocks, the number of transactions will be changed

f[i][j] state transition equation

If the i-1th day is in the buying state, then do nothing on the i-th day, and the i-th day is also in the buying state
In this case: f[i][j]=f[i-1][j];


If the i-1th day is in the selling state, then the i-th day is in the buying state.
You need to subtract the price[i] corresponding to buying the stock.
In this case: f[i][j]=g[i-1][ j]-price[i];


The state transition equation is:
f[i][j]=max(f[i-1][j],g[i-1][j]-price[i]);

g[i][j] state transition equation

If the i-1th day is in the selling state, then do nothing on the i-th day, then the i-th day is also in the selling state
In this case: g[i][j]=g[i-1][j] ;


If the i-1th day is in the buying state, then the i-th day is in the selling state. The
profit price[i] corresponding to selling stocks needs to be added,
because the state from buying to selling is completed, the number of transactions on the i-th day +1 becomes j. At this time, j is +1 on the original number of times
and the number of transactions on the i-1th day is still the original number of times. Therefore, it should be j-1
from buying stocks to selling stocks. Calculate the completion of a transaction
assuming that j is 0, then buy stocks on the i-1th day, the number of transactions is 0
and sell stocks on the i-th day, the number of transactions is 1

In this case: g[i][j]=f[i-1][j-1]+price[i];


The state transition equation is:
g[i][j]= max(g[i-1][j],f[i-1][j-1]+price[i]);

initialization

For the state transition equation of g[i][j], when j is 0, -1 transaction is completed on the i-1 day, this situation does not exist, so the state of g[i][j] can
be The transfer equation is modified


In the first step, assign g[i][j] to g[i-1][j], so directly replace g[i-1][j] with g[i][j in the if loop ] In this way, -1 transactions
can be avoided


Assuming k is 2, there are three situations: 0 transactions, 1 transaction, 2 transactions

The ordinate indicates that after the end of the i-th day,
the abscissa indicates the completion of the i transaction
. When the ordinate is 0, it means that 0/1/2 transactions are completed after the end of the 0th day. This situation does not exist. Buying
and selling on the same day , there is no profit, and the number of transactions is limited,
so in order not to interfere with the subsequent results, after the end of the 0th day, when 1/2 transactions are completed, they are all set to negative infinity


f[0][0]: Indicates that after the end of the 0th day, it is in the buying state, that is, buying the stock will cost money, and the profit will be negative
f[0][0]=-price[0];


g[0][0]: Indicates that after the end of the 0th day, it is in a selling state (after the end of the 0th day, there is no stock in hand, and it cannot be sold, which is equivalent to doing nothing, and the profit is 0) g[
0 ][0]=0;


If int_min is selected for negative infinity, an
out-of-bounds problem will occur Negative infinity selection -0x3f3f3f3f(0x3f3f3f3f is half of the maximum value of int)\

full code

class Solution {
    
    
public:
    int maxProfit(int k, vector<int>& prices) {
    
    
       int n=prices.size();
       //将k进行优化
       k=min(k,n/2);
         //f 表示买入状态 g表示卖出状态
       //有[0,k-1] 笔交易
       vector<vector<int>>f(n,vector<int>(k+1,-0x3f3f3f));  
       vector<vector<int>>g(n,vector<int>(k+1,-0x3f3f3f));

       //初始化
       f[0][0]=-prices[0];
       g[0][0]=0;
       int i=0;
       int j=0;
       for(i=1;i<n;i++)
       {
    
    
           for(j=0;j<=k;j++)
           {
    
    
              f[i][j]=max(f[i-1][j],g[i-1][j]-prices[i]);
            //修改后的状态转移方程
              g[i][j]=g[i-1][j];
              if(j-1>=0)
              {
    
    
                  g[i][j]=max(g[i][j],f[i-1][j-1]+prices[i]);
              }
           }
       }
       //寻找g的最后一行的最大值
       int ret=INT_MIN;
       for(j=0;j<=k;j++)
       {
    
    
           if(ret<g[n-1][j])
           {
    
    
               ret=g[n-1][j];
           }
       }
       //返回g的最后一行的最大值
       return ret;
    }
};

If there are 20 days, k (number of transactions) is 30,
and the maximum number of transactions is only 10, so optimize
k=min(k,n/2);
(n/2 represents the maximum number of transactions)

53. Maximum Subarray Sum

Click to view: Maximum Subarray Sum


state transition equation

Get all the sub-arrays that end with i, such as: i position itself, combination of i and i-1 position, combination of i and i-2 position, combination of i and subscript 0 position, etc. Take the generated sub-arrays among them
and the biggest one

dp[i]: Indicates the maximum sum of all subarrays ending with the i position element


dp[i] can be divided into two categories:

1. The i position element itself (length is 1)
in this case: dp[i]= nums[i]


2. The i position element is combined with the previous element (length greater than 1)

Because what is required is the maximum sum of the sub-arrays ending at position i, you should first find the maximum sum of the sub-arrays ending at position i-1, that is, add nums[i] to dp[i-1], which
is The i position is the maximum sum of sub-arrays at the end
In this case: dp[i]=dp[i-1]+nums[i];

initialization

If i is 0, it is an out-of-bounds problem

In order to prevent this kind of out-of-bounds problem, a virtual node is added to
the expanded array. The subscript of the virtual node is 0, and the element subscript of the original array starts from 1.

If it is dp[1], dp[1]=max(nums[1],dp[0]+nums[1])
in order not to interfere with the result , set the value of dp[0] to 0

full code

class Solution {
    
    
public:
    int maxSubArray(vector<int>& nums) {
    
    
       int n=nums.size();
       //dp作为扩展数组 所以比原数组大1
       vector<int>dp(n+1,0);

       int i=0;
       //因为dp表可能都为负,所以初始值为最小值
       int ret=INT_MIN;
       for(i=1;i<n+1;i++)
       {
    
    
           //当前下标i作为扩展数组dp的下标 
           //想要使用dp下标 找到对应 原数组nums对应值
           //应该使用i-1
           dp[i]=max(nums[i-1],dp[i-1]+nums[i-1]);
           //寻找dp表的最大值
           if(ret<dp[i])
           {
    
    
               ret=dp[i];
           }
       }

       return ret;

    }
};

Guess you like

Origin blog.csdn.net/qq_62939852/article/details/131462419