1. Topic description
LeetCode 122. The Best Times to Buy and Sell Stocks II
On each day, you can decide whether to buy and/or sell shares. You can hold no more than one share at any one time. You can also buy first and then sell it the same day. Return the maximum profit you can make.
Example:
*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), the exchange will earn profit = 5 - 1 = 4.
Then, by buying on day 4 (stock price = 3) and selling on day 5 (stock price = 6), the exchange will earn a profit = 6 - 3 = 3.
The total profit is 4 + 3 = 7. *
This problem is common and not difficult. It is interesting that there are many solutions, especially suitable for entry-level monotonic stacks and dynamic programming.
2. Greedy algorithm
This is the easiest solution to think of, because the number of transactions is not limited, and you only need to buy at the bottom of each upslope of the stock price and sell at the top of the slope, then you must maximize the benefits
function maxProfit(prices){
let ans = 0;
for (let i = 0; i < prices.length - 1; i++) {
if (prices[i + 1] > prices[i]) { // 在上坡过程中,【每天都交易】和【底部买入,坡顶卖出】是完全等效的(忽略手续费)
ans += (prices[i + 1] - prices[i]);
}
}
return ans
}
3. Monotonic stack
Monotonic stack, as the name suggests, is a stack structure with monotonically increasing/decreasing. The representation of the upslope of the stock price in the data structure is actually an increasing monotonic stack. We only need to find all the upslopes in turn, at which time the top of the stack is subtracted from the bottom of the stack. , is the maximum profit of a single uphill
function maxProfit(prices){
//这里只末尾+0就够了
prices.push(0) //前后+0,是单调栈很常见的处理措施,确保起止元素一定能形成首个坡,终止末个的坡
let ans = 0
let stack = []
for (let i = 0; i < prices.length; i++) {
//stack[stack.length - 1] 单调栈栈顶,即本次上坡最大值
if(stack.length > 0 && prices[i] < stack[stack.length - 1]){
//栈顶
let top = stack[stack.length - 1]
//栈底
let bottom = stack[0]
ans += top - bottom
stack = []//清栈
}
stack.push(prices[i])
}
return ans
}
The monotonic stack is mainly discussed here, so the stack structure is retained. In fact, this question is relatively simple. It can be simplified by simply recording the top and bottom of the stack:
function maxProfit(prices){
prices.push(0)
let ans = 0
let top = prices[0]
let bottom = prices[0]
for (let i = 0; i < prices.length; i++) {
if(prices[i] >= top){
top = prices[i]
}else{
ans += top - bottom
top = bottom = prices[i]
}
}
return ans
}
This question is the most basic application of the monotonic stack. The complex ones, such as rainwater , and the largest rectangle in the histogram , are all application scenarios of the monotonic stack. In a word, the monotonic stack is a powerful and interesting data structure.
4. Dynamic programming
It is not difficult to see that there are only two states of holding and short positions every day:
For today's position status, the maximum balance of today's account is the larger of [Yesterday's Position] and [Yesterday's Short Position - Today's Stock Price] (deduct money for purchase)
For today's short position status, the maximum balance of today's account is the larger of [Yesterday's short position] and [Yesterday's position + today's stock price] (add money for selling)
Close the position on the last day, that is, the account balance in the short position state is the maximum profit to obtain the state transition equation:
$$ for position status f(i)_hold = max( f(i-1)_hold, + f(i-1)_empty - price[i] )$$
$$ for short position f(i)_empty = max( f(i-1)_empty, + f(i-1)_hold + price[i] )$$
function maxProfit(prices){
//最初始的状态
let dp = []
dp.push(
{
'positon': -prices[0],//持仓
'short_positon':0//空仓
}
)
for (let i = 1; i < prices.length; i++) {
let status = {
//本次选择持仓,则账户最大金额为max(昨天持仓,昨天空仓-今日股价)
'positon': Math.max(dp[i-1].positon, dp[i-1].short_positon - prices[i]),
//本次选择空仓,则账户最大金额为max(昨天空仓,昨天持仓+今日股价)
'short_positon': Math.max(dp[i-1].short_positon, dp[i-1].positon + prices[i])
}
}
return dp[prices.length-1].short_positon
}
Since only yesterday's data is used, there is no need to store the daily position status, just record yesterday.
After simplification:
function maxProfit(prices){
//最初始的状态
let positon = -prices[0] //持仓
let short_positon = 0 //空仓
for (let i = 1; i < prices.length; i++) {
let new_positon = Math.max(positon, short_positon - prices[i])
let new_short_positon = Math.max(short_positon, positon + prices[i])
positon = new_positon
short_positon = new_short_positon
}
return short_positon
}
Dynamic programming is a powerful and interesting algorithm.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。