Design a stack that supports getMin() in O(1) time and O(1) extra space

Question: 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 be O(1). To implement SpecialStack, you should only use standard Stack data structure and no other data structure like arrays, list, .. etc.

Example:

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.

An approach that uses O(1) time and O(n) extra space is discussed here.



In this article, a new approach is discussed that supports minimum with O(1) extra space. 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 minimum element is removed. To handle this, we push “2x – minEle” into the stack instead of x so that previous minimum element can be retrieved using current minEle and its value stored in stack. Below are detailed steps and explanation of working.

Push(x) : Inserts x at the top of stack.

Pop() : Removes an element from top of stack.

Important Points:

Illustration

Push(x)

Pop()

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to implement a stack that supports
// getMinimum() in O(1) time and O(1) extra space.
#include <bits/stdc++.h>
using namespace std;
  
// A user defined stack that supports getMin() in
// addition to push() and pop()
struct MyStack
{
    stack<int> s;
    int minEle;
  
    // Prints minimum element of MyStack
    void getMin()
    {
        if (s.empty())
            cout << "Stack is empty\n";
  
        // variable minEle stores the minimum element
        // in the stack.
        else
            cout <<"Minimum Element in the stack is: "
                 << minEle << "\n";
    }
  
    // Prints top element of MyStack
    void peek()
    {
        if (s.empty())
        {
            cout << "Stack is empty ";
            return;
        }
  
        int t = s.top(); // Top element.
  
        cout << "Top Most Element is: ";
  
        // If t < minEle means minEle stores
        // value of t.
        (t < minEle)? cout << minEle: cout << t;
    }
  
    // Remove the top element from MyStack
    void pop()
    {
        if (s.empty())
        {
            cout << "Stack is empty\n";
            return;
        }
  
        cout << "Top Most Element Removed: ";
        int t = s.top();
        s.pop();
  
        // Minimum will change as the minimum element
        // of the stack is being removed.
        if (t < minEle)
        {
            cout << minEle << "\n";
            minEle = 2*minEle - t;
        }
  
        else
            cout << t << "\n";
    }
  
    // Removes top element from MyStack
    void push(int x)
    {
        // Insert new number into the stack
        if (s.empty())
        {
            minEle = x;
            s.push(x);
            cout <<  "Number Inserted: " << x << "\n";
            return;
        }
  
        // If new number is less than minEle
        if (x < minEle)
        {
            s.push(2*x - minEle);
            minEle = x;
        }
  
        else
           s.push(x);
  
        cout <<  "Number Inserted: " << x << "\n";
    }
};
  
// Driver Code
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;
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to implement a stack that supports
// getMinimum() in O(1) time and O(1) extra space.
import java.util.*;
  
// A user defined stack that supports getMin() in
// addition to push() and pop()
class MyStack
{
    Stack<Integer> s;
    Integer minEle;
  
    // Constructor
    MyStack() { s = new Stack<Integer>(); }
  
    // Prints minimum element of MyStack
    void getMin()
    {
        // Get the minimum number in the entire stack
        if (s.isEmpty())
            System.out.println("Stack is empty");
  
        // variable minEle stores the minimum element
        // in the stack.
        else
            System.out.println("Minimum Element in the " +
                               " stack is: " + minEle);
    }
  
    // prints top element of MyStack
    void peek()
    {
        if (s.isEmpty())
        {
            System.out.println("Stack is empty ");
            return;
        }
  
        Integer t = s.peek(); // Top element.
  
        System.out.print("Top Most Element is: ");
  
        // If t < minEle means minEle stores
        // value of t.
        if (t < minEle)
            System.out.println(minEle);
        else
            System.out.println(t);
    }
  
    // Removes the top element from MyStack
    void pop()
    {
        if (s.isEmpty())
        {
            System.out.println("Stack is empty");
            return;
        }
  
        System.out.print("Top Most Element Removed: ");
        Integer t = s.pop();
  
        // Minimum will change as the minimum element
        // of the stack is being removed.
        if (t < minEle)
        {
            System.out.println(minEle);
            minEle = 2*minEle - t;
        }
  
        else
            System.out.println(t);
    }
  
    // Insert new number into MyStack
    void push(Integer x)
    {
        if (s.isEmpty())
        {
            minEle = x;
            s.push(x);
            System.out.println("Number Inserted: " + x);
            return;
        }
  
        // If new number is less than original minEle
        if (x < minEle)
        {
            s.push(2*x - minEle);
            minEle = x;
        }
  
        else
            s.push(x);
  
        System.out.println("Number Inserted: " + x);
    }
};
  
// Driver Code
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();
    }
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# Class to make a Node 
class Node:
    # Constructor which assign argument to nade's value 
    def __init__(self, value):
        self.value = value
        self.next = None
  
    # This method returns the string representation of the object.
    def __str__(self):
        return "Node({})".format(self.value)
      
    # __repr__ is same as __str__
    __repr__ = __str__
  
  
class Stack:
    # Stack Constructor initialise top of stack and counter.
    def __init__(self):
        self.top = None
        self.count = 0
        self.minimum = None
          
    # This method returns the string representation of the object (stack).
    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__ is same as __str__
    __repr__=__str__
      
    # This method is used to get minimum element of stack
    def getMin(self):
        if self.top is None:
            return "Stack is empty"
        else:
            print("Minimum Element in the stack is: {}" .format(self.minimum))
  
  
  
    # Method to check if Stack is Empty or not
    def isEmpty(self):
        # If top equals to None then stack is empty 
        if self.top == None:
            return True
        else:
        # If top not equal to None then stack is empty 
            return False
  
    # This method returns length of stack     
    def __len__(self):
        self.count = 0
        tempNode = self.top
        while tempNode:
            tempNode = tempNode.next
            self.count+=1
        return self.count
  
    # This method returns top of stack     
    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))
  
    # This method is used to add node to stack
    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))
  
    # This method is used to pop top of stack
    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))
  
                  
              
      
# Driver program to test above class 
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()
  
# This code is contributed by Blinkii
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to implement a stack 
// that supports getMinimum() in O(1) 
// time and O(1) extra space.
using System;
using System.Collections;
  
// A user defined stack that supports 
// getMin() in addition to Push() and Pop()
public class MyStack
{
    public Stack s;
    public int minEle;
  
    // Constructor
    public MyStack() 
    {
        s = new Stack();
    }
  
    // Prints minimum element of MyStack
    public void getMin()
    {
        // Get the minimum number 
        // in the entire stack
        if (s.Count==0)
            Console.WriteLine("Stack is empty");
  
        // variable minEle stores the minimum 
        // element in the stack.
        else
            Console.WriteLine("Minimum Element in the " +
                            " stack is: " + minEle);
    }
  
    // prints top element of MyStack
    public void Peek()
    {
        if (s.Count==0)
        {
            Console.WriteLine("Stack is empty ");
            return;
        }
  
        int t =(int)s.Peek(); // Top element.
  
        Console.Write("Top Most Element is: ");
  
        // If t < minEle means minEle stores
        // value of t.
        if (t < minEle)
            Console.WriteLine(minEle);
        else
            Console.WriteLine(t);
    }
  
    // Removes the top element from MyStack
    public void Pop()
    {
        if (s.Count==0)
        {
            Console.WriteLine("Stack is empty");
            return;
        }
  
        Console.Write("Top Most Element Removed: ");
        int t = (int)s.Pop();
  
        // Minimum will change as the minimum element
        // of the stack is being removed.
        if (t < minEle)
        {
            Console.WriteLine(minEle);
            minEle = 2*minEle - t;
        }
  
        else
            Console.WriteLine(t);
    }
  
    // Insert new number into MyStack
    public void Push(int x)
    {
        if (s.Count==0)
        {
            minEle = x;
            s.Push(x);
            Console.WriteLine("Number Inserted: " + x);
            return;
        }
  
        // If new number is less than original minEle
        if (x < minEle)
        {
            s.Push(2 * x - minEle);
            minEle = x;
        }
  
        else
            s.Push(x);
  
        Console.WriteLine("Number Inserted: " + x);
    }
}
  
// Driver Code
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();
    }
}
  
// This code is contributed by Arnab Kundu
chevron_right


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

How does this approach work?
When element to be inserted is less than minEle, we insert “2x – minEle”. The important thing to notes is, 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
 

Exercise:
Similar approach can be used to find the maximum element as well. Implement a stack that supports getMax() in O(1) time and constant extra space.

This article is contributed by Nikhil Tekwani. If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.




Improved By : andrew1234, Blinkii



Article Tags :