Open In App

Queue with Minimum

Last Updated : 20 Sep, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Design a SpecialQueue that supports enqueue(x), dequeue(), getFront(), and getMin() in O(1) time.

  • enqueue(x) → insert element x at the rear of the queue
  • dequeue() → remove the element from the front of the queue
  • getFront() → return the front element without removing; -1 if empty
  • getMin() → return the minimum element in the queue; -1 if empty

Input: operations[] = [enqueue(4), enqueue(2), enqueue(1), getMin(), enqueue(6), dequeue(), getFront(), getMin()]
Output: [1, 2, 1]
Explanation:
enqueue(4): Queue = [4]
enqueue(2): Queue = [4, 2]
enqueue(1): Queue = [4, 2, 1]
getMin(): Minimum element is 1
enqueue(6): Queue = [4, 2, 1, 6]
dequeue(): Removes 4 → Queue = [2, 1, 6]
getFront(): Front element is 2
getMin(): Minimum element is 1

[Approach] Using Dequeue - O(1) Time and O(n) Space

The idea is to use an auxiliary Deque to keep track of minimum elements while maintaining normal queue operations. By storing elements in sorted order inside the Deque, we can always retrieve the minimum in O(1) time.

Working of the Approach:

Enqueue(x):
-> Insert x into the main queue (q1).
-> In the deque (q2), remove all elements from the back that are larger than x (since they can’t be the minimum anymore), then insert x at the back.

Dequeue():
-> Remove the front element from the main queue (q1).
-> If this element is equal to the front of the deque (q2), also remove it from the deque to keep both structures in sync.

getMin(): Return the front of the deque (q2.front()), which always stores the current minimum element in the queue.

getFront(): Return the front element of the main queue (q1.front()), i.e., the element that would be removed first if dequeue() is called.

Note: In JavaScript, there’s no built-in queue, so we implement a custom queue using a doubly linked list for O(1) enqueue and dequeue.

C++
#include <iostream>
#include <queue>
#include <deque>
using namespace std;

class SpecialQueue {
    queue<int> q1;
    deque<int> q2;

public:
    // Insert element into the queue
    void enqueue(int x) {
        q1.push(x);
        while (!q2.empty() && q2.back() > x) {
            q2.pop_back();
        }
        q2.push_back(x);
    }

    // Remove element from the queue
    void dequeue() {
        if (q1.empty()) {
            cout << "Queue is empty\n";
            return;
        }
        int frontVal = q1.front();
        if (frontVal == q2.front()) {
            q2.pop_front();
        }
        q1.pop();
    }

    // Get minimum element
    int getMin() {
        if (q1.empty()) {
            cout << "Queue is empty\n";
            return -1;
        }
        return q2.front();
    }

    // Get front element
    int getFront() {
        if (q1.empty()) {
            cout << "Queue is empty\n";
            return -1;
        }
        return q1.front();
    }
};

int main() {
   SpecialQueue q;

    q.enqueue(4);
    q.enqueue(2);
    q.enqueue(1);
    cout << q.getMin() <<" ";   
    q.enqueue(6);
    q.dequeue();                  
    cout << q.getFront() <<" "; 
    cout << q.getMin() <<" ";   

    return 0;
}
Java
import java.util.Queue;
import java.util.Deque;
import java.util.LinkedList;

class SpecialQueue {
    Queue<Integer> q1 = new LinkedList<>();
    Deque<Integer> q2 = new LinkedList<>();

    // Insert element into the queue
    public void enqueue(int x) {
        q1.add(x);
        while (!q2.isEmpty() && q2.peekLast() > x) {
            q2.removeLast();
        }
        q2.addLast(x);
    }

    // Remove element from the queue
    public void dequeue() {
        if (q1.isEmpty()) {
            System.out.println("Queue is empty");
            return;
        }
        int frontVal = q1.peek();
        if (frontVal == q2.peekFirst()) {
            q2.removeFirst();
        }
        q1.remove();
    }

    // Get minimum element
    public int getMin() {
        if (q1.isEmpty()) {
            System.out.println("Queue is empty");
            return -1;
        }
        return q2.peekFirst();
    }

    // Get front element
    public int getFront() {
        if (q1.isEmpty()) {
            System.out.println("Queue is empty");
            return -1;
        }
        return q1.peek();
    }
}

public class GFG {
    public static void main(String[] args) {
        SpecialQueue q = new SpecialQueue();

        q.enqueue(4);
        q.enqueue(2);
        q.enqueue(1);
        System.out.print(q.getMin() + " ");   
        q.enqueue(6);
        q.dequeue();                  
        System.out.print(q.getFront() + " "); 
        System.out.print(q.getMin() + " ");   
    }
}
Python
from collections import deque

class SpecialQueue:
    def __init__(self):
        
        # main queue
        self.q1 = deque()  
        self.q2 = deque()  
        
    # Insert element into the queue
    def enqueue(self, x):
        self.q1.append(x)
        while self.q2 and self.q2[-1] > x:
            self.q2.pop()
        self.q2.append(x)

    # Remove element from the queue
    def dequeue(self):
        if not self.q1:
            print("Queue is empty")
            return
        frontVal = self.q1.popleft()
        if frontVal == self.q2[0]:
            self.q2.popleft()

    # Get minimum element
    def getMin(self):
        if not self.q1:
            print("Queue is empty")
            return -1
        return self.q2[0]

    # Get front element
    def getFront(self):
        if not self.q1:
            print("Queue is empty")
            return -1
        return self.q1[0]

if __name__ == "__main__":
    q = SpecialQueue()

    q.enqueue(4)
    q.enqueue(2)
    q.enqueue(1)
    print(q.getMin(), end=" ") 
    q.enqueue(6)
    q.dequeue()
    print(q.getFront(), end=" ")  
    print(q.getMin(), end=" ")    
C#
using System;
using System.Collections.Generic;

class SpecialQueue {
    Queue<int> q1 = new Queue<int>();
    LinkedList<int> q2 = new LinkedList<int>();

    // Insert element into the queue
    public void enqueue(int x) {
        q1.Enqueue(x);
        while (q2.Count > 0 && q2.Last.Value > x) {
            q2.RemoveLast();
        }
        q2.AddLast(x);
    }

    // Remove element from the queue
    public void dequeue() {
        if (q1.Count == 0) {
            Console.WriteLine("Queue is empty");
            return;
        }
        int frontVal = q1.Peek();
        if (frontVal == q2.First.Value) {
            q2.RemoveFirst();
        }
        q1.Dequeue();
    }

    // Get minimum element
    public int getMin() {
        if (q1.Count == 0) {
            Console.WriteLine("Queue is empty");
            return -1;
        }
        return q2.First.Value;
    }

    // Get front element
    public int getFront() {
        if (q1.Count == 0) {
            Console.WriteLine("Queue is empty");
            return -1;
        }
        return q1.Peek();
    }
}

class GFG {
    static void Main(string[] args) {
        SpecialQueue q = new SpecialQueue();

        q.enqueue(4);
        q.enqueue(2);
        q.enqueue(1);
        Console.Write(q.getMin() + " ");
        q.enqueue(6);
        q.dequeue();
        Console.Write(q.getFront() + " ");
        Console.Write(q.getMin() + " ");
    }
}
JavaScript
// Node class for doubly linked list
class Node {
    constructor(data) {
        this.data = data;
        this.prev = null;
        this.next = null;
    }
}

// Queue implemented using doubly linked list
class Queue {
    constructor() {
        this.front = null;
        this.rear = null;
        this.size = 0;
    }

    // Add element at the rear
    enqueue(x) {
        let node = new Node(x);
        if (!this.rear) {
            this.front = this.rear = node;
        } else {
            node.prev = this.rear;
            this.rear.next = node;
            this.rear = node;
        }
        this.size++;
    }

    // Remove element from the front
    dequeue() {
        if (!this.front) return null;
        let val = this.front.data;
        this.front = this.front.next;
        if (this.front) this.front.prev = null;
        else this.rear = null;
        this.size--;
        return val;
    }

    // Get front element
    getFront() {
        return this.front ? this.front.data : null;
    }

    isEmpty() {
        return this.size === 0;
    }
}

// SpecialQueue using Queue class and maintaining min
class SpecialQueue {
    constructor() {
        this.q1 = new Queue(); // main queue
        this.q2 = new Queue(); // track minimum
    }

    // Insert element into the queue
    enqueue(x) {
        this.q1.enqueue(x);

        // maintain min queue
        while (!this.q2.isEmpty() && this.q2.rear.data > x) {
            // remove from rear
            this.q2.rear = this.q2.rear.prev;
            if (this.q2.rear) this.q2.rear.next = null;
            else this.q2.front = null;
            this.q2.size--;
        }
        this.q2.enqueue(x);
    }

    // Remove element from the queue
    dequeue() {
        if (this.q1.isEmpty()) {
            console.log("Queue is empty");
            return;
        }
        let frontVal = this.q1.dequeue();
        if (frontVal === this.q2.getFront()) {
            this.q2.dequeue();
        }
    }

    // Get minimum element
    getMin() {
        if (this.q1.isEmpty()) {
            console.log("Queue is empty");
            return -1;
        }
        return this.q2.getFront();
    }

    // Get front element
    getFront() {
        if (this.q1.isEmpty()) {
            console.log("Queue is empty");
            return -1;
        }
        return this.q1.getFront();
    }
}

// Driver Code
const q = new SpecialQueue();

q.enqueue(4);
q.enqueue(2);
q.enqueue(1);
process.stdout.write(q.getMin() + " ");
q.enqueue(6);
q.dequeue();
process.stdout.write(q.getFront() + " ");
process.stdout.write(q.getMin() + " ");  

Output
1 2 1 

Article Tags :

Explore