Design a Queue data structure to get minimum or maximum in O(1) time
Last Updated :
01 Nov, 2023
Problem: Design a Data Structure a SpecialQueue which supports following operations enqueue, deque, getMin() or getMax() where getMin() operation takes O(1) time.
Example:
Let the data to be inserted in queue be -
4, 2, 1, 6Operation Queue Output
push(4) 4 -
push(2) 4, 2 -
push(1) 4, 2, 1 -
getMin() 4, 2, 1 1
push(6) 4, 2, 1, 6 -
pop() 2, 1, 6 4
pop() 1, 6 2
pop() 6 1
getMin() 6 6// Notice the getMin() function call
// It returns the minimum element
// of all the values present in the queue
Approach: The idea is to use Doubly ended Queue to store in increasing order if the structure is to return the minimum element and store in decreasing order if the structure is to return the maximum element. The operations of the Data Structure is defined as follows:
Enqueue
- Insert the element into the queue structure.
- If the size of the Deque structure is empty that is the size of the Deque is 0. Then, Insert the element from the back.
- Otherwise, If there are some elements in the Deque structure then pop the elements out from the Deque until the back of the Deque is greater than the current element and then finally insert the element from back.
Deque
- If the first element of the Deque is equal to the front element of the queue then pop the elements out from the Queue and the Deque at the same time.
- Otherwise, Pop the element from the front of the queue to maintain the order of the elements.
Get Minimum
Return the front element of the Deque to get the minimum element of the current element of the queue.
Below is the implementation of the above approach:
C++
// C++ implementation to design
// a queue data structure to get
// minimum element in O(1) time
#include <bits/stdc++.h>
using namespace std;
template <typename T>
// Structure of the queue
class MinMaxQueue {
public:
// Queue to store the
// element to maintain the
// order of insertion
queue<T> Q;
// Doubly ended queue to
// get the minimum element
// in the O(1) time
deque<T> D;
// Function to push a element
// into the queue
void enque_element(T element)
{
// If there is no element
// in the queue
if (Q.size() == 0) {
Q.push(element);
D.push_back(element);
}
else {
Q.push(element);
// Pop the elements out
// until the element at
// back is greater than
// current element
while (!D.empty() && D.back() > element) {
D.pop_back();
}
D.push_back(element);
}
}
// Function to pop the element
// out from the queue
void deque_element()
{
// Condition when the Minimum
// element is the element at
// the front of the Deque
if (Q.front() == D.front()) {
Q.pop();
D.pop_front();
}
else {
Q.pop();
}
}
// Function to get the
// minimum element from
// the queue
T getMin() { return D.front(); }
};
// Driver Code
int main()
{
MinMaxQueue<int> k;
int example[3] = { 1, 2, 4 };
// Loop to enque element
for (int i = 0; i < 3; i++) {
k.enque_element(example[i]);
}
cout << k.getMin() << "\n";
k.deque_element();
cout << k.getMin() << "\n";
}
Java
import java.io.*;
import java.util.*;
class SpecialQueue {
Queue<Integer> q;
Deque<Integer> dq;
public SpecialQueue()
{
q = new LinkedList<>();
dq = new ArrayDeque<>();
}
void enque(int data)
{
// remove all elements from
// from deque which are greater
// than the current element 'data'
while (!dq.isEmpty() && dq.getLast() > data) {
dq.removeLast();
}
// If queue is empty then
// while loop is skipped.
dq.addLast(data);
q.add(data);
}
void deque()
{
// If min element is present
// at front of queue
if (dq.getFirst() == q.peek()) {
dq.removeFirst();
}
q.remove();
}
// Method to get min element in Queue
int getMin() throws Exception
{
// If queue is Empty, return Exception
if (q.isEmpty())
throw new Exception("Queue is Empty");
else
return dq.getFirst();
}
public static void main(String[] args) throws Exception
{
SpecialQueue arr = new SpecialQueue();
arr.enque(1);
arr.enque(2);
arr.enque(4);
System.out.println(arr.getMin());
arr.deque();
System.out.println(arr.getMin());
}
}
Python3
# Python 3 implementation to design
# a queue data structure to get
# minimum element in O(1) time
from collections import deque as dq
# class for the queue
class MinMaxQueue:
def __init__(self):
# Queue to store the
# element to maintain the
# order of insertion
self.Q = dq([])
# Doubly ended queue to
# get the minimum element
# in the O(1) time
self.D = dq([])
# Function to push a element
# into the queue
def enque_element(self, element):
# If there is no element
# in the queue
if (len(self.Q) == 0):
self.Q.append(element)
self.D.append(element)
else:
self.Q.append(element)
# Pop the elements out
# until the element at
# back is greater than
# current element
while (self.D and
self.D[-1] > element):
self.D.pop()
self.D.append(element)
# Function to pop the element
# out from the queue
def deque_element(self,):
# Condition when the Minimum
# element is the element at
# the front of the Deque
if (self.Q[0] == self.D[0]):
self.Q.popleft()
self.D.popleft()
else:
self.Q.popleft()
# Function to get the
# minimum element from
# the queue
def getMin(self,):
return self.D[0]
# Driver Code
if __name__ == '__main__':
k = MinMaxQueue()
example = [1, 2, 4]
# Loop to enque element
for i in range(3):
k.enque_element(example[i])
print(k.getMin())
k.deque_element()
print(k.getMin())
C#
using System;
using System.Collections.Generic;
class SpecialQueue {
Queue<int> q;
List<int> dq;
public SpecialQueue()
{
q = new Queue<int>();
dq = new List<int>();
}
void Enque(int data)
{
// remove all elements from
// from deque which are greater
// than the current element 'data'
while (dq.Count > 0 && dq[dq.Count - 1] > data) {
dq.RemoveAt(dq.Count - 1);
}
// If queue is empty then
// while loop is skipped.
dq.Add(data);
q.Enqueue(data);
}
void Deque()
{
// If min element is present
// at front of queue
if (dq[0] == q.Peek()) {
dq.RemoveAt(0);
}
q.Dequeue();
}
// Method to get min element in Queue
int GetMin()
{
// If queue is Empty, return Exception
if (q.Count == 0) {
throw new Exception("Queue is Empty");
}
else {
return dq[0];
}
}
public static void Main(string[] args)
{
SpecialQueue arr = new SpecialQueue();
arr.Enque(1);
arr.Enque(2);
arr.Enque(4);
Console.WriteLine(arr.GetMin());
arr.Deque();
Console.WriteLine(arr.GetMin());
}
}
// This code is contributed by phasing17
JavaScript
class MinMaxQueue {
constructor() {
// Queue to store the element to maintain the order of insertion
this.Q = [];
// Doubly ended queue to get the minimum element in the O(1) time
this.D = [];
}
// Function to push a element into the queue
enqueElement(element) {
// If there is no element in the queue
if (this.Q.length === 0) {
this.Q.push(element);
this.D.push(element);
} else {
this.Q.push(element);
// Pop the elements out until the element at back is greater than current element
while (this.D.length > 0 && this.D[this.D.length - 1] > element) {
this.D.pop();
}
this.D.push(element);
}
}
// Function to pop the element out from the queue
dequeElement() {
// Condition when the Minimum element is the element at the front of the Deque
if (this.Q[0] === this.D[0]) {
this.Q.shift();
this.D.shift();
} else {
this.Q.shift();
}
}
// Function to get the minimum element from the queue
getMin() {
return this.D[0];
}
}
// Driver Code
function main() {
const k = new MinMaxQueue();
const example = [1, 2, 4];
// Loop to enque element
for (let i = 0; i < 3; i++) {
k.enqueElement(example[i]);
}
console.log(k.getMin());
k.dequeElement();
console.log(k.getMin());
}
main();
// This code is contributed by phasing17
Time and Space of Complexity of Each Function:
enque function:
- Time complexity: O(N), where N is the number of elements in the deque
- Auxiliary Space: O(N)
deque() method:
- Time complexity: O(1)
- Auxiliary Space: O(1)
getMin() method:
- Time complexity: O(1)
- Auxiliary Space: O(1)
Similar Reads
Find maximum in stack in O(1) without using additional stack The task is to design a stack which can get the maximum value in the stack in O(1) time without using an additional stack. Examples: Input: push(2) findMax() push(6) findMax() pop() findMax() Output: 2 inserted in stack Maximum value in the stack: 2 6 inserted in stack Maximum value in the stack: 6
11 min read
Perform given queries on Queue according to the given rules Given a queue consisting of the first N natural numbers and queries Query[][] of the type {E, X}, the task is to perform the given queries on the given queue according to the following rules: If the value of E is 1, then pop the front element from the queue.If the value of E is 2, then remove the va
8 min read
How to Create a Stack of Priority_Queue in C++? In C++, std::stack is a container that follows the LIFO (Last In, First Out) rule, whereas std::priority_queue is a type of queue in which the first element is either the greatest(by default) or the smallest of all elements in the queue. In this article, we will learn how to create a stack of a prio
2 min read
How to Find the Maximum Element in a Deque in C++? in C++, double-ended queues, also known as deques, are sequence containers with the feature of insertion and deletion on both ends. They are similar to vectors but are more efficient for the insertion and deletion of elements from both ends. In this article, we will learn how to find the maximum ele
2 min read
Design Front Middle Back Queue using STL Design a data structure that supports the following operations in queue efficiently: push__front(x): Insert an element at the front of the queue.push__middle(x): Inserts element at the middle of the queue.push__back(x): Inserts element at the back of the queue.pop__front() Removes the front element
8 min read