Monotonous queue = double-end queue!
Let's start with the simplest problem:
Given an integer Series A (I), I = 0, 1,..., N-1 and Window Length k.
Requirements:
F (I) = max {A (I-k + 1), a (I-K + 2 ),..., A (I)}, I = 0, 1 ,..., n-1
Another description of the problem is to use a K-length window to move over the integer series and find the maximum number contained in the window.
Solution 1:
A very intuitive solution is to put the window at the beginning of the series, find the maximum number of K at the beginning, and then move the last unit in the window, continue to find the maximum value in K number.
Every time f (I) is obtained for this method, the K-1 times are compared, and the complexity is O (n * K ).
Is there any faster algorithm?
Solution 2:
We know that the previous algorithm has a place that is repeated comparison, that is, when looking for the current f (I), I in front of the number of K-1 other in the calculation of F (I-1) we have compared it. So can we save the last result? Of course, it is the maximum number of K-1 before I. The answer is yes. This requires a monotonic decreasing queue.
The monotonic decreasing queue is such a queue. Its Header element is always the maximum value in the queue, and the values in the queue are arranged in descending order. We can insert an element from the end of the queue to delete the element from both ends of the queue.
1. first, let's look at the inserted element: to ensure the progressive reduction of the queue, we need to compare the elements at the end of the team with those at the end of the team when inserting element V. If the element at the end of the team is not greater than that at the end of the team, then, the elements at the end of the team are deleted, and the new elements at the end of the team are compared with those at the end of the team until the elements at the end of the team are greater than those at the end of the team.
2. The deletion at the end of the team has just been mentioned. When will the first element be deleted? Since we only need to save the maximum value of the first K-1 element of I, when the index or subscript of the first element of the team is smaller than I-k + 1, it means that the first element of the team has no significance for F (I), because it is no longer in the window. Therefore, when index [first element] <I-k + 1, delete the first element.
From the above introduction, we know that the only difference between a monotonous queue and a queue is that it not only stores the value of elements, in addition, you need to save the index of the element (of course, in actual application, you only need to save the index, and indirectly find the value of the current index through the index ).
To give readers a better understanding, let me give a simple example.
Suppose the number of columns is: 8, 7, 12, 5, 16, 9, 17,2, 4, 6.n= 10, K = 3.
Then we construct a monotonically decreasing queue with a length of 3:
First, the 8 and its index 0 are put into the queue, which is represented by (8, 0). When each step inserts an element, the elements in the queue are as follows:
0: insert 8, queue: (8, 0)
1: insert 7, queue: (8, 0), (7, 1)
2: insert 12, queue: (12, 2)
3: insert 5, queue: (12, 2), (5, 3)
4: insert 16, queue: (16, 4)
5: insert 9, queue: (16, 4), (9, 5)
.... And so on
Then f (I) is the first element in the queue at step I: 8, 12, 12, 16, 16 ,...
I'm a split line ------------------------------------------------------------------------------
PS: deque interface of STL
Deque, meaning double ended Queue (dual-end Queue), which is often read as deck. The method is similar to that of vector, and the interface is basically the same as that of vector. As for the differences between the two and the advantages and disadvantages of the two, the preceding Excerpt from Master Hou's book also gives a clear explanation. The container itself is not absolutely good or bad. The key lies in the application environment and needs.
The member function table is as follows:
Function |
Description |
Assign (beg, end) Assign (n, ELEM) |
Assign values to the data in the [beg; End) interval. Assign a copy value to n elem instances. |
At (idx) |
Returns the data specified by the index idx. If idx is out of bounds, out_of_range is thrown. |
Back () |
Returns the last data and does not check whether the data exists. |
Begin () |
Returns the unique data of the iterator. |
Clear () |
Remove all data from the container |
Deque C1 (C2) Deque C (n) Deque C (n, ELEM) Deque C (beg, end) ~ Deque () |
Copy A deque Create a deque that contains N pieces of data, which are created by default. Create a deque Containing n elem copies Create a deque in the [beg; End) Interval Destroys all data and releases memory. |
Empty () |
Judge whether the container is empty |
End () |
Point to the last data address in the iterator |
Erase (POS) Erase (beg, end) |
Deletes the data at the POs position and returns the location of the next data. Delete the data in the [beg, end) interval and return the location of the next data. |
Front () |
Return a data record |
Get_allocator |
Returns a copy using the constructor. |
Insert (Pos, ELEM) Insert (Pos, N, ELEM) Insert (Pos, beg, end) |
Insert an ELEM copy at the POs position and return the new data location. Insert n ELEM data at the POs position, with no returned value Data inserted in the [beg, end) range at the POs position, no return value |
Max_size () |
Maximum number of returned data in the container |
Pop_back () |
Delete the last data |
Pop_front () |
Delete header data |
Push_back (ELEM) |
Add data at the end |
Push_front (ELEM) |
Insert a data entry in the header |
Rbegin () |
Returns the first data of a reverse queue. |
Rend () |
Returns the next location of the last data in a reverse queue. |
Resize (Num) |
Specify the queue length again |
Size () |
Returns the actual number of data in the container. |
C1.swap (C2) Swap (C1, C2) |
Swap C1 and C2 Elements Same as above |
OPERATOR [] |
Returns a reference from a specified position in the container. |