Summary and application of monotone stack template

Articles and codes have been archived in [Github warehouse: https://github.com/timerring/algorithms-notes] or the official account [AIShareLab ] can also be obtained by replying to algorithm notes.

Monotonic Stack Template

Stack: first in last out.

Queue: first in first out.

Compared with STL, the advantage of array simulation stack and queue is that it is fast. Although there will be O2 optimization during actual compilation, which makes the two almost the same, there is generally no optimization in algorithm problems.

Stack Algorithm Template

// 栈定义为stk[N],tt表示栈顶,初始化为0
int stk[N], tt = 0;

// 向栈顶插入一个数
stk[ ++ tt] = x;

// 从栈顶弹出一个数
tt -- ;

// 栈顶的值
stk[tt];

// 判断栈是否为空
/*
	if(tt > 0) not empty
	else empty
*/
if (tt > 0)
{
    
    
	
}

The monotonic stack is commonly used for a given number, to find where the number closest to him and smaller than him is on the left side of each number in this sequence.

Example: Monotonic Stack

Given a sequence of integers of length N, output the first smaller number to the left of each number, or −1 if it does not exist.

input format

The first line contains the integer N, which represents the length of the sequence.

The second row contains N integers, representing a sequence of integers.

output format

A total of one line, containing N integers, where the i-th number represents the first number on the left of the i-th number that is smaller than it, and if it does not exist, output −1.

data range

1 ≤ N ≤ 1 0 5 1≤N≤10^5 1N105
1 ≤ 1≤ 1≤Elements in the array≤1 0 9 ≤10^9109

Input sample:

5
3 4 2 7 5

Sample output:

-1 3 -1 2 2

The basic idea

Define a stack, read in data separately, and then judge the number in the stack. If the number at the top of the stack is greater than or equal to the read x, then pop the number out of the stack (eliminate all numbers greater than it) until the number at the top of the stack is less than the number, output the number, and then store x on the top of the stack. This ensures that the numbers in the stack are always stored linearly. That is, the input x can find the nearest smaller number than him.

code

# include <iostream>

using namespace std;

const int N = 100010;

int n;
int stk[N], tt;

int main()
{
    
    
    cin >> n;
    
    for(int i = 0; i < n; i++)
    {
    
    
        int x;
        cin >> x;
        while(tt && stk[tt] >= x) tt --; // 如果栈顶元素大于当前待入栈元素,则出栈
        if(tt) cout << stk[tt] << ' '; // 如果栈不空,则该栈顶元素就是左侧第一个比它小的元素
        else cout << -1 << ' '; // 如果栈空,则没有比该元素小的值,输出 -1
        // 再将该元素添加进去
        stk[ ++ tt] = x;
    }
    
    return 0;
}

Although there are two loops in this algorithm, actually for the second loop, there are only two operations of push and pop for each number, and no traversal is involved, so the time consumption is 2N, and the time complexity is O(N ).

The same can also be achieved using STL:

#include<iostream>
#include<vector>
using namespace std;
int main() {
    
    
    int n,x;
    cin >> n;
    vector<int> t;
    while (n--) {
    
    
        cin >> x;
        while (t.size() > 0 and t.back() >= x) {
    
    
            t.pop_back();
        }
        if (t.size() == 0) {
    
    
            cout << -1 << ' ';
        }else {
    
    
            cout << t.back()<<' ';
        }
        t.push_back(x);
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_52316372/article/details/130654885