Open In App

Introduction to Monotonic Queues

 A monotonic queue is a data structure that supports efficient insertion, deletion, and retrieval of elements in a specific order, typically in increasing or decreasing order.

The monotonic queue can be implemented using different data structures, such as a linked list, stack, or deque. The most common implementation is using a deque (double-ended queue) container. The deque container allows efficient insertion and deletion of elements from both the front and back of the queue, which is useful for implementing a monotonic queue.



There are two main types of monotonic queues:

Implement the idea below to solve the Increasing Monotonic Queue problem:



Here’s an example of an increasing monotonic queue implemented in C++:




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// Function to solve Increasing
// Monotonic queue
deque<int> increasing_monotonic_queue(int arr[], int n)
{
 
    deque<int> q;
    for (int i = 0; i < n; i++) {
 
        // If recently added element is
        // greater current element
        while (!q.empty() && q.back() > arr[i]) {
 
            q.pop_back();
        }
 
        q.push_back(arr[i]);
    }
 
    return q;
}
 
// Driver code
int main()
{
 
    int arr[] = { 1, 2, 3, 4, 5, 6 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Function call
    deque<int> q = increasing_monotonic_queue(arr, n);
 
    for (int i : q) {
        cout << i << " ";
    }
    return 0;
}




// Java code for the above approach:
import java.util.*;
 
class GFG {
    // Function to solve Increasing
    // Monotonic queue
    static Deque<Integer>
    increasing_monotonic_queue(int arr[], int n)
    {
 
        Deque<Integer> q = new LinkedList<Integer>();
        for (int i = 0; i < n; i++) {
 
            // If recently added element is
            // greater current element
            while (!q.isEmpty() && q.getLast() > arr[i]) {
 
                q.removeLast();
            }
 
            q.addLast(arr[i]);
        }
 
        return q;
    }
 
    // Driver code
    public static void main(String[] args)
    {
 
        int arr[] = { 1, 2, 3, 4, 5, 6 };
        int n = arr.length;
 
        // Function call
        Deque<Integer> q
            = increasing_monotonic_queue(arr, n);
 
        Iterator it = q.iterator();
        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
    }
}




from collections import deque
 
def increasing_monotonic_queue(arr, n):
    q = deque()
    for i in range(n):
        while len(q) > 0 and q[-1] > arr[i]:
            q.pop()
        q.append(arr[i])
    return q
 
arr = [1, 2, 3, 4, 5, 6]
n = len(arr)
q = increasing_monotonic_queue(arr, n)
for i in q:
    print(i, end=' ')




// C# code for the above approach:
 
using System;
using System.Collections.Generic;
 
public class GFG {
 
    // Function to solve Increasing Monotonic queue
    static Queue<int> IncreasingMonotonicQueue(int[] arr)
    {
        Queue<int> q = new Queue<int>();
        for (int i = 0; i < arr.Length; i++) {
            // If recently added element is greater than the
            // current element
            while (q.Count > 0 && q.Peek() > arr[i]) {
                q.Dequeue();
            }
 
            q.Enqueue(arr[i]);
        }
 
        return q;
    }
 
    static public void Main()
    {
 
        // Code
        int[] arr = { 1, 2, 3, 4, 5, 6 };
        // Function call
        Queue<int> q = IncreasingMonotonicQueue(arr);
 
        foreach(int i in q) { Console.Write(i + " "); }
    }
}
 
// This code is contributed by karthik.




// Function to solve Increasing
// Monotonic queue
function increasing_monotonic_queue(arr, n) {
    const q = [];
 
    for (let i = 0; i < n; i++) {
        // If recently added element is greater than the current element
        while (q.length > 0 && q[q.length - 1] > arr[i]) {
            q.pop();
        }
 
        q.push(arr[i]);
    }
 
    return q;
}
 
// Driver code
const arr = [1, 2, 3, 4, 5, 6];
const n = arr.length;
const q = increasing_monotonic_queue(arr, n);
 
q.forEach((i) => {
    process.stdout.write(i + " ");
});

Output
1 2 3 4 5 6 

Implement the idea below to solve the Decreasing Monotonic Queue problem:

Here is an example of a decreasing monotonic queue implemented in C++:




// C++ code for the above approach
#include <deque>
#include <iostream>
using namespace std;
 
// Function to calculate Decreasing
// Monotonic queue
deque<int> decreasing_monotonic_queue(int arr[], int n)
{
 
    deque<int> q;
    for (int i = 0; i < n; i++) {
 
        // If recently added element is
        // smaller than current element
        while (!q.empty() && q.back() < arr[i]) {
 
            q.pop_back();
        }
 
        q.push_back(arr[i]);
    }
 
    return q;
}
 
// Driver Code
int main()
{
    int arr[] = { 6, 5, 4, 3, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Function call
    deque<int> q = decreasing_monotonic_queue(arr, n);
 
    for (int i : q) {
        cout << i << " ";
    }
 
    return 0;
}




// Java code for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
 
  // Function to calculate Decreasing Monotonic queue
  public static Deque<Integer>
    decreasing_monotonic_queue(int[] arr)
  {
    Deque<Integer> q = new ArrayDeque<>();
    int n = arr.length;
    for (int i = 0; i < n; i++)
    {
 
      // If recently added element is smaller than
      // current element
      while (!q.isEmpty() && q.peekLast() < arr[i]) {
        q.pollLast();
      }
      q.offerLast(arr[i]);
    }
    return q;
  }
 
  public static void main(String[] args)
  {
    int[] arr = { 6, 5, 4, 3, 2, 1 };
     
    // Function call
    Deque<Integer> q = decreasing_monotonic_queue(arr);
    for (int i : q) {
      System.out.print(i + " ");
    }
  }
}
 
// This code is contributed by sankar.




from collections import deque
 
# Function to calculate Decreasing
# Monotonic queue
def decreasing_monotonic_queue(arr):
    n = len(arr)
    q = deque()
    for i in range(n):
 
        # If recently added element is
        # smaller than current element
        while q and q[-1] < arr[i]:
 
            q.pop()
 
        q.append(arr[i])
 
    return q
 
# Driver Code
arr = [6, 5, 4, 3, 2, 1]
 
# Function call
q = decreasing_monotonic_queue(arr)
 
for i in q:
    print(i)




using System;
using System.Collections.Generic;
 
class Program
{
    // Function to calculate Decreasing
    // Monotonic queue
    static LinkedList<int> decreasing_monotonic_queue(int[] arr, int n)
    {
        LinkedList<int> q = new LinkedList<int>();
        for (int i = 0; i < n; i++)
        {
            // If recently added element is
            // smaller than current element
            while (q.Count > 0 && q.Last.Value < arr[i])
            {
                q.RemoveLast();
            }
 
            q.AddLast(arr[i]);
        }
 
        return q;
    }
 
    // Driver Code
    static void Main()
    {
        int[] arr = { 6, 5, 4, 3, 2, 1 };
        int n = arr.Length;
 
        // Function call
        LinkedList<int> q = decreasing_monotonic_queue(arr, n);
 
        foreach (int i in q)
        {
            Console.Write(i + " ");
        }
        Console.WriteLine();
    }
}
// This code is contributed by Prajwal Kandekar




// Function to calculate Decreasing
// Monotonic queue
function decreasingMonotonicQueue(arr) {
  const n = arr.length;
  const q = [];
  for (let i = 0; i < n; i++) {
    // If recently added element is
    // smaller than current element
    while (q.length && q[q.length - 1] < arr[i]) {
      q.pop();
    }
    q.push(arr[i]);
  }
  return q;
}
 
// Driver Code
const arr = [6, 5, 4, 3, 2, 1];
 
// Function call
const q = decreasingMonotonicQueue(arr);
 
for (const i of q) {
  process.stdout.write(i+' ');
}

Output
6 5 4 3 2 1 

Applications of monotonic queue include:

Advantages of the monotonic queue:

Disadvantages of the monotonic queue:


Article Tags :