Design a stack that supports getMin() in O(1) time and O(1) extra space
Last Updated :
17 Apr, 2023
Design a Data Structure SpecialStack that supports all the stack operations like push(), pop(), isEmpty(), isFull() and an additional operation getMin() which should return minimum element from the SpecialStack. All these operations of SpecialStack must have a time and space complexity of O(1).
Note: To implement SpecialStack, you should only use standard Stack data structure and no other data structure like arrays, lists, etc
Example:
Input: Consider the following SpecialStack
16 –> TOP
15
29
19
18
When getMin() is called it should return 15,
which is the minimum element in the current stack.
If we do pop two times on stack, the stack becomes
29 –> TOP
19
18
When getMin() is called, it should return 18
which is the minimum in the current stack.
Approach: To solve the problem follow the below idea:
We define a variable minEle that stores the current minimum element in the stack. Now the interesting part is, how to handle the case when the minimum element is removed. To handle this, we push “2x – minEle” into the stack instead of x so that the previous minimum element can be retrieved using the current minEle and its value stored in the stack
Follow the given steps to implement the stack operations:
Push(x): Insert x at the top of the stack
- If the stack is empty, insert x into the stack and make minEle equal to x.
- If the stack is not empty, compare x with minEle. Two cases arise:
- If x is greater than or equal to minEle, simply insert x.
- If x is less than minEle, insert (2*x – minEle) into the stack and make minEle equal to x.
For example, let the previous minEle be 3. Now we want to insert 2. We update minEle as 2 and insert 2*2 – 3 = 1 into the stack
Pop(): Removes an element from the top of the stack
- Remove the element from the top. Let the removed element be y. Two cases arise:
- If y is greater than or equal to minEle, the minimum element in the stack is still minEle.
- If y is less than minEle, the minimum element now becomes (2*minEle – y), so update (minEle = 2*minEle – y). This is where we retrieve the previous minimum from the current minimum and its value in the stack.
For example, let the element to be removed be 1 and minEle be 2. We remove 1 and update minEle as 2*2 – 1 = 3
Important Points:
- Stack doesn’t hold the actual value of an element if it is minimum so far.
- The actual minimum element is always stored in the minEle variable
Below is the illustration of the above approach:
Push(x)
- Number to be Inserted: 3, Stack is empty, so insert 3 into stack and minEle = 3.
- Number to be Inserted: 5, Stack is not empty, 5> minEle, insert 5 into stack and minEle = 3.
- Number to be Inserted: 2, Stack is not empty, 2< minEle, insert (2*2-3 = 1) into stack and minEle = 2.
- Number to be Inserted: 1, Stack is not empty, 1< minEle, insert (2*1-2 = 0) into stack and minEle = 1.
- Number to be Inserted: 1, Stack is not empty, 1 = minEle, insert 1 into stack and minEle = 1.
- Number to be Inserted: -1, Stack is not empty, -1 < minEle, insert (2*-1 – 1 = -3) into stack and minEle = -1.
Pop()
- Initially the minimum element minEle in the stack is -1.
- Number removed: -3, Since -3 is less than the minimum element the original number being removed is minEle which is -1, and the new minEle = 2*-1 – (-3) = 1
- Number removed: 1, 1 == minEle, so number removed is 1 and minEle is still equal to 1.
- Number removed: 0, 0< minEle, original number is minEle which is 1 and new minEle = 2*1 – 0 = 2.
- Number removed: 1, 1< minEle, original number is minEle which is 2 and new minEle = 2*2 – 1 = 3.
- Number removed: 5, 5> minEle, original number is 5 and minEle is still 3
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
struct MyStack {
stack< int > s;
int minEle;
void getMin()
{
if (s.empty())
cout << "Stack is empty\n" ;
else
cout << "Minimum Element in the stack is: "
<< minEle << "\n" ;
}
void peek()
{
if (s.empty()) {
cout << "Stack is empty " ;
return ;
}
int t = s.top();
cout << "Top Most Element is: " ;
(t < minEle) ? cout << minEle : cout << t;
}
void pop()
{
if (s.empty()) {
cout << "Stack is empty\n" ;
return ;
}
cout << "Top Most Element Removed: " ;
int t = s.top();
s.pop();
if (t < minEle) {
cout << minEle << "\n" ;
minEle = 2 * minEle - t;
}
else
cout << t << "\n" ;
}
void push( int x)
{
if (s.empty()) {
minEle = x;
s.push(x);
cout << "Number Inserted: " << x << "\n" ;
return ;
}
else if (x < minEle) {
s.push(2 * x - minEle);
minEle = x;
}
else
s.push(x);
cout << "Number Inserted: " << x << "\n" ;
}
};
int main()
{
MyStack s;
s.push(3);
s.push(5);
s.getMin();
s.push(2);
s.push(1);
s.getMin();
s.pop();
s.getMin();
s.pop();
s.peek();
return 0;
}
|
Java
import java.util.*;
class MyStack {
Stack<Integer> s;
Integer minEle;
MyStack() { s = new Stack<Integer>(); }
void getMin()
{
if (s.isEmpty())
System.out.println( "Stack is empty" );
else
System.out.println( "Minimum Element in the "
+ " stack is: " + minEle);
}
void peek()
{
if (s.isEmpty()) {
System.out.println( "Stack is empty " );
return ;
}
Integer t = s.peek();
System.out.print( "Top Most Element is: " );
if (t < minEle)
System.out.println(minEle);
else
System.out.println(t);
}
void pop()
{
if (s.isEmpty()) {
System.out.println( "Stack is empty" );
return ;
}
System.out.print( "Top Most Element Removed: " );
Integer t = s.pop();
if (t < minEle) {
System.out.println(minEle);
minEle = 2 * minEle - t;
}
else
System.out.println(t);
}
void push(Integer x)
{
if (s.isEmpty()) {
minEle = x;
s.push(x);
System.out.println( "Number Inserted: " + x);
return ;
}
if (x < minEle) {
s.push( 2 * x - minEle);
minEle = x;
}
else
s.push(x);
System.out.println( "Number Inserted: " + x);
}
};
public class Main {
public static void main(String[] args)
{
MyStack s = new MyStack();
s.push( 3 );
s.push( 5 );
s.getMin();
s.push( 2 );
s.push( 1 );
s.getMin();
s.pop();
s.getMin();
s.pop();
s.peek();
}
}
|
Python 3
class Node:
def __init__( self , value):
self .value = value
self . next = None
def __str__( self ):
return "Node({})" . format ( self .value)
__repr__ = __str__
class Stack:
def __init__( self ):
self .top = None
self .count = 0
self .minimum = None
def __str__( self ):
temp = self .top
out = []
while temp:
out.append( str (temp.value))
temp = temp. next
out = '\n' .join(out)
return ( 'Top {} \n\nStack :\n{}' . format ( self .top, out))
__repr__ = __str__
def getMin( self ):
if self .top is None :
return "Stack is empty"
else :
print ( "Minimum Element in the stack is: {}" . format ( self .minimum))
def isEmpty( self ):
if self .top = = None :
return True
else :
return False
def __len__( self ):
self .count = 0
tempNode = self .top
while tempNode:
tempNode = tempNode. next
self .count + = 1
return self .count
def peek( self ):
if self .top is None :
print ( "Stack is empty" )
else :
if self .top.value < self .minimum:
print ( "Top Most Element is: {}" . format ( self .minimum))
else :
print ( "Top Most Element is: {}" . format ( self .top.value))
def push( self , value):
if self .top is None :
self .top = Node(value)
self .minimum = value
elif value < self .minimum:
temp = ( 2 * value) - self .minimum
new_node = Node(temp)
new_node. next = self .top
self .top = new_node
self .minimum = value
else :
new_node = Node(value)
new_node. next = self .top
self .top = new_node
print ( "Number Inserted: {}" . format (value))
def pop( self ):
if self .top is None :
print ( "Stack is empty" )
else :
removedNode = self .top.value
self .top = self .top. next
if removedNode < self .minimum:
print ( "Top Most Element Removed :{} " . format ( self .minimum))
self .minimum = (( 2 * self .minimum) - removedNode)
else :
print ( "Top Most Element Removed : {}" . format (removedNode))
if __name__ = = '__main__' :
stack = Stack()
stack.push( 3 )
stack.push( 5 )
stack.getMin()
stack.push( 2 )
stack.push( 1 )
stack.getMin()
stack.pop()
stack.getMin()
stack.pop()
stack.peek()
|
C#
using System;
using System.Collections;
public class MyStack {
public Stack s;
public int minEle;
public MyStack() { s = new Stack(); }
public void getMin()
{
if (s.Count == 0)
Console.WriteLine( "Stack is empty" );
else
Console.WriteLine( "Minimum Element in the "
+ " stack is: " + minEle);
}
public void Peek()
{
if (s.Count == 0) {
Console.WriteLine( "Stack is empty " );
return ;
}
int t = ( int )s.Peek();
Console.Write( "Top Most Element is: " );
if (t < minEle)
Console.WriteLine(minEle);
else
Console.WriteLine(t);
}
public void Pop()
{
if (s.Count == 0) {
Console.WriteLine( "Stack is empty" );
return ;
}
Console.Write( "Top Most Element Removed: " );
int t = ( int )s.Pop();
if (t < minEle) {
Console.WriteLine(minEle);
minEle = 2 * minEle - t;
}
else
Console.WriteLine(t);
}
public void Push( int x)
{
if (s.Count == 0) {
minEle = x;
s.Push(x);
Console.WriteLine( "Number Inserted: " + x);
return ;
}
if (x < minEle) {
s.Push(2 * x - minEle);
minEle = x;
}
else
s.Push(x);
Console.WriteLine( "Number Inserted: " + x);
}
}
public class main {
public static void Main(String[] args)
{
MyStack s = new MyStack();
s.Push(3);
s.Push(5);
s.getMin();
s.Push(2);
s.Push(1);
s.getMin();
s.Pop();
s.getMin();
s.Pop();
s.Peek();
}
}
|
Javascript
class MyStack {
constructor() {
this .s = [];
this .minEle;
}
getMin() {
if ( this .s.length == 0)
console.log( "Stack is empty" );
else
console.log( "Minimum Element in the stack is: " , this .minEle);
}
peek() {
if ( this .s.length == 0) {
console.log( "Stack is empty " );
return ;
}
let t = this .s[0];
console.log( "Top Most Element is: " );
(t < this .minEle) ? console.log( this .minEle) : console.log(t);
}
pop() {
if ( this .s.length == 0) {
console.log( "Stack is empty " );
return ;
}
console.log( "Top Most Element Removed: " );
let t = this .s[0];
this .s.shift();
if (t < this .minEle) {
console.log( this .minEle);
this .minEle = (2 * this .minEle) - t;
}
else
console.log(t);
}
push(x) {
if ( this .s.length == 0) {
this .minEle = x;
this .s.unshift(x);
console.log( "Number Inserted: " , x);
return ;
}
else if (x < this .minEle) {
this .s.unshift(2 * x - this .minEle);
this .minEle = x;
}
else
this .s.unshift(x);
console.log( "Number Inserted: " , x);
}
};
let s = new MyStack;
s.push(3);
s.push(5);
s.getMin();
s.push(2);
s.push(1);
s.getMin();
s.pop();
s.getMin();
s.pop();
s.peek();
|
Output
Number Inserted: 3
Number Inserted: 5
Minimum Element in the stack is: 3
Number Inserted: 2
Number Inserted: 1
Minimum Element in the stack is: 1
Top Most Element Removed: 1
Minimum Element in the stack is: 2
Top Most Element Removed: 2
Top Most Element is: 5
Time Complexity: O(1)
Auxiliary Space: O(1)
How does this approach work?
When the element to be inserted is less than minEle, we insert “2x – minEle”. The important thing to note is, that 2x – minEle will always be less than x (proved below), i.e., new minEle and while popping out this element we will see that something unusual has happened as the popped element is less than the minEle. So we will be updating minEle.
How 2*x – minEle is less than x in push()?
x < minEle which means x – minEle < 0
// Adding x on both sides
x – minEle + x < 0 + x
2*x – minEle < x
We can conclude 2*x – minEle < new minEle
While popping out, if we find the element(y) less than the current minEle, we find the new minEle = 2*minEle – y
How previous minimum element, prevMinEle is, 2*minEle – y
in pop() is y the popped element?
// We pushed y as 2x – prevMinEle. Here
// prevMinEle is minEle before y was inserted
y = 2*x – prevMinEle
// Value of minEle was made equal to x
minEle = x .
new minEle = 2 * minEle – y
= 2*x – (2*x – prevMinEle)
= prevMinEle // This is what we wanted
Design a stack that supports getMin() in O(1) time and O(1) extra space by creating a MinStack class:
To solve the problem follow the below idea:
Create a class node that has two variables Val and min. Val will store the actual value that we are going to insert in the stack, whereas min will store the min value so far seen up to that node
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int mini( int a, int b) { return a > b ? b : a; }
class MinStack {
public :
stack<pair< int , int > > s;
void push( int element)
{
int new_min = s.empty()
? element
: mini(element, s.top().second);
s.push({ element, new_min });
}
int pop()
{
int popped;
if (!s.empty()) {
popped = s.top().first;
s.pop();
}
else {
}
return popped;
}
int minimum()
{
int min_elem = s.top().second;
return min_elem;
}
};
int main()
{
MinStack s;
s.push(-1);
s.push(10);
s.push(-4);
s.push(0);
cout << s.minimum() << endl;
cout << s.pop() << endl;
cout << s.pop() << endl;
cout << s.minimum();
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class MinStack {
Stack<Node> s;
class Node {
int val;
int min;
public Node( int val, int min)
{
this .val = val;
this .min = min;
}
}
/** initialize your data structure here. */
public MinStack() { this .s = new Stack<Node>(); }
public void push( int x)
{
if (s.isEmpty()) {
this .s.push( new Node(x, x));
}
else {
int min = Math.min( this .s.peek().min, x);
this .s.push( new Node(x, min));
}
}
public int pop() { return this .s.pop().val; }
public int top() { return this .s.peek().val; }
public int getMin() { return this .s.peek().min; }
}
class GFG {
public static void main(String[] args)
{
MinStack s = new MinStack();
s.push(- 1 );
s.push( 10 );
s.push(- 4 );
s.push( 0 );
System.out.println(s.getMin());
System.out.println(s.pop());
System.out.println(s.pop());
System.out.println(s.getMin());
}
}
|
Python3
class MinStack:
def __init__( self ):
self .s = []
class Node:
def __init__( self , val, Min ):
self .val = val
self . min = Min
def push( self , x):
if not self .s:
self .s.append( self .Node(x, x))
else :
Min = min ( self .s[ - 1 ]. min , x)
self .s.append( self .Node(x, Min ))
def pop( self ):
return self .s.pop().val
def top( self ):
return self .s[ - 1 ].val
def getMin( self ):
return self .s[ - 1 ]. min
s = MinStack()
s.push( - 1 )
s.push( 10 )
s.push( - 4 )
s.push( 0 )
print (s.getMin())
print (s.pop())
print (s.pop())
print (s.getMin())
|
C#
using System;
using System.Collections.Generic;
public class MinStack {
Stack<Node> s;
public class Node {
public int val;
public int min;
public Node( int val, int min)
{
this .val = val;
this .min = min;
}
}
public MinStack() { this .s = new Stack<Node>(); }
public void push( int x)
{
if (s.Count == 0) {
this .s.Push( new Node(x, x));
}
else {
int min = Math.Min( this .s.Peek().min, x);
this .s.Push( new Node(x, min));
}
}
public int pop() { return this .s.Pop().val; }
public int top() { return this .s.Peek().val; }
public int getMin() { return this .s.Peek().min; }
}
public class GFG {
public static void Main(String[] args)
{
MinStack s = new MinStack();
s.push(-1);
s.push(10);
s.push(-4);
s.push(0);
Console.WriteLine(s.getMin());
Console.WriteLine(s.pop());
Console.WriteLine(s.pop());
Console.WriteLine(s.getMin());
}
}
|
Javascript
function mini(a,b) { return a > b ? b : a; }
class MinStack {
constructor()
{
this .s = new Array();
}
pushE(element)
{
let new_min = 0;
if ( this .s.length==0)
new_min = element;
else
new_min = mini(element, this .s[ this .s.length-1].second);
this .s.push({
first:element,
second:new_min
});
}
popE()
{
let popped;
if ( this .s.length>0) {
popped = this .s[ this .s.length-1].first;
this .s.pop();
}
else {
}
return popped;
}
minimum()
{
let min_elem = this .s[ this .s.length-1].second;
return min_elem;
}
};
let s = new MinStack();
s.pushE(-1);
s.pushE(10);
s.pushE(-4);
s.pushE(0);
console.log(s.minimum());
console.log(s.popE());
console.log(s.popE());
console.log(s.minimum());
|
Related Article: An approach that uses O(1) time and O(n) extra space is discussed here.
Please Login to comment...