Chapter II Data Structure Monotonic Stack and Monotonic Queue

Keywords: C Algorithm data structure

1. Algorithmic ideas

The core idea of these two algorithms is:
Only those elements that conform to a certain monotonicity are likely to be the answer. Screen out those elements that do not conform to a monotonicity according to the title requirements, store those elements that conform to a certain monotonicity in the stack or queue, and obtain the maximum and minimum values of these elements according to the title (usually at the top of the stack, at the head of the queue, at the end of the queue)Or, depending on monotonicity, the values of certain elements can be obtained by dichotomy.
That's abstract. Let's look at two examples for analysis.
These two algorithms can handle a limited variety of topics, so more can be accumulated.

2. Example Analysis

1. Monotonic Stack

Theme link: Monotonic stack

Given a length of N An integer column that outputs the first lower number to the left of each number, or if it does not exist −1. 

Input Format
 The first line contains integers N,Represents the length of a column.

The second line contains N An integer representing an integer column.

Output Format
 One line, containing N Integers, of which i Number represents number i The first number to the left of the number smaller than it, or output if it does not exist −1. 

Data Range
1≤N≤10^5
1≤Elements in Columns≤10^9
 Input sample:
5
3 4 2 7 5
 Output sample:
-1 3 -1 2 2

1. Idea analysis

This can also be changed to look for the first (smaller) number on the right that is larger than this number.

  • Think about violence first
    Violent practice is to use a double loop, and for each number, start over and look for the first smaller number to the left of each number.
  • Watch what kind of elements can never be the answer
    Let's consider 4 and 2 in the sample. For elements after 2, if 4 is smaller than that element, then 2 must be smaller than that element, and 2 is closer to that element than 4, so for elements after 2, 4 will never be the answer. Generally, if x and y are in reverse order (that is, if x<y and X is more to the right than y)So for the elements to the right of x, it is impossible to select the element y. So for the elements to the right of x, the elements that may be selected must be monotonically increasing in order (because anything in reverse order cannot be selected). We use stacks to store the elements that may be selected, the closer to the top of the stack, the larger and the more to the right.

2. Code implementation

#include<cstdio>
using namespace std;
const int N = 1e5 + 10;
int stk[N],tt;
int main()
{
	int n;
	scanf("%d",&n);
	for(int i = 0; i < n; i ++)
	{
		int tmp;
		scanf("%d",&tmp);
		while(tt && stk[tt] >= tmp)
		{
			tt --;
		}
		if(tt == 0)
		{
			printf("-1 ");
		}else{
			printf("%d ",stk[tt]);
		}
		stk[++ tt] = tmp;
	}
}

3. Time Complexity Analysis

Although it looks like a double loop, for while inside, it executes up to n times in total, so the algorithm time complexity is O ( n ) O(n) O(n)

2. Monotonic Queues

Theme link: sliding window

Given a size of n≤10^6 Array.
There is a size of k The sliding window of the array moves from the leftmost to the rightmost.
You can only see it in the window k Numbers.
Slide the window one position to the right each time.

Here is an example:
The array is [1 3 -1 -3 5 3 6 7],k 3.

window position					minimum value        	Maximum
[1 3 -1] -3 5 3 6 7	     -1				  3
1 [3 -1 -3] 5 3 6 7	     -3				  3
1 3 [-1 -3 5] 3 6 7	     -3				  5
1 3 -1 [-3 5 3] 6 7	     -3				  5
1 3 -1 -3 [5 3 6] 7	      3				  6
1 3 -1 -3 5 [3 6 7]	      3				  7
 Your task is to determine the maximum and minimum values in the sliding window at each location.

Input Format
 The input contains two lines.
The first line contains two integers n and k,Represents the length of the array and the length of the sliding window, respectively.
The second line has n Integers representing the specific values of the array.
Peer data is separated by spaces.

Output Format
 The output contains two.

The first line of output, from left to right, slides the minimum value in the window at each location.
The second line of output, from left to right, slides the maximum value in the window at each location.

Input sample:
8 3
1 3 -1 -3 5 3 6 7
 Output sample:
-1 -3 -3 -3 3 3
3 3 5 5 6 7

1. Idea analysis

  • Consider violent practices first. Traverse through each selected interval to pick the maximum and minimum values.
  • Watch what elements are not selected as answers
    Assuming we seek the minimum, k = 3, we consider the interval [-1-3 5] in the sampleFor example, when -3 appears, the -1 ahead of him can never be called the result of an interval. Because -1 is not only larger than -3, but -3 is also later than -1, leaving the interval later, that is, -1 leaves the interval before -3 leaves the interval, and because -1 is larger than -3, it is impossible for -1 to be the result at this time. So for each new element entering the interval, the interval at this time is not possible anymore.All elements larger than it will no longer be the answer, that is, all possible answers are less than it. So we use a queue to maintain all possible numbers in the zone that will be the answer. Every time a number is inserted, a number larger than it will be expelled from the queue, which always maintains a monotonic queue from small to large.

2. Code implementation

#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int q[N],s[N],h,t;

int main()
{
    int n,k;
    cin >> n >> k;
    for(int i = 0; i < n; i ++)
    {
        cin >> s[i];
    }
    
    for(int i = 0; i < n; i ++)
    {
        if(h != t && i - k + 1 > q[h]) h ++;
        while(h != t && s[q[t - 1]] > s[i]) t --;
        q[t ++] = i;
        if(i >= k - 1 && t != h)
        cout << s[q[h]] << " ";
    }
    cout << endl;
    h = 0,t = 0;
    for(int i = 0; i < n; i ++)
    {
        if(h != t && i - k + 1 > q[h])h ++;
        while(h != t && s[q[t - 1]] < s[i]) t --;
        q[t ++] = i;
        if(i >= k - 1 && t != h)
        cout << s[q[h]] << " ";
    }
}

3. Time Complexity Analysis

Each element in while is queued only once, so there are 2 total operations with a time complexity of O ( n ) O(n) O(n)

Reference material

Acwing

Posted by Trey395 on Tue, 21 Sep 2021 09:40:12 -0700