Find maximum in stack in O(1) without using additional stack
Last Updated :
04 Apr, 2023
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
Element popped
Maximum value in the stack: 2
Approach: Instead of pushing a single element to the stack, push a pair instead. The pair consists of the (value, localMax) where localMax is the maximum value upto that element.
- When we insert a new element, if the new element is greater than the local maximum below it, we set the local maximum of a new element equal to the element itself.
- Else, we set the local maximum of the new element equal to the local maximum of the element below it.
- The local maximum of the top of the stack will be the overall maximum.
- Now if we want to know the maximum at any given point, we ask the top of the stack for local maximum associated with it which can be done in O(1).
Below is the implementation of the above approach:
C++
// C++ implementation of the approach
#include <iostream>
using namespace std;
struct Block {
// A block has two elements
// as components
int value, localMax;
};
class Stack {
private:
// Pointer of type block,
// Will be useful later as the
// size can be dynamically allocated
struct Block* S;
int size, top;
public:
Stack(int);
void push(int);
void pop();
void max();
};
Stack::Stack(int n)
{
// Setting size of stack and
// initial value of top
size = n;
S = new Block[n];
top = -1;
}
// Function to push an element to the stack
void Stack::push(int n)
{
// Doesn't allow pushing elements
// if stack is full
if (top == size - 1) {
cout << "Stack is full" << endl;
}
else {
top++;
// If the inserted element is the first element
// then it is the maximum element, since no other
// elements is in the stack, so the localMax
// of the first element is the element itself
if (top == 0) {
S[top].value = n;
S[top].localMax = n;
}
else {
// If the newly pushed element is
// less than the localMax of element below it,
// Then the over all maximum doesn't change
// and hence, the localMax of the newly inserted
// element is same as element below it
if (S[top - 1].localMax > n) {
S[top].value = n;
S[top].localMax = S[top - 1].localMax;
}
// Newly inserted element is greater than the localMax
// below it, hence the localMax of new element
// is the element itself
else {
S[top].value = n;
S[top].localMax = n;
}
}
cout << n << " inserted in stack" << endl;
}
}
// Function to remove an element
// from the top of the stack
void Stack::pop()
{
// If stack is empty
if (top == -1) {
cout << "Stack is empty" << endl;
}
// Remove the element if the stack
// is not empty
else {
top--;
cout << "Element popped" << endl;
}
}
// Function to find the maximum
// element from the stack
void Stack::max()
{
// If stack is empty
if (top == -1) {
cout << "Stack is empty" << endl;
}
else {
// The overall maximum is the local maximum
// of the top element
cout << "Maximum value in the stack: "
<< S[top].localMax << endl;
}
}
// Driver code
int main()
{
// Create stack of size 5
Stack S1(5);
S1.push(2);
S1.max();
S1.push(6);
S1.max();
S1.pop();
S1.max();
return 0;
}
Java
// Java implementation of the approach
class GFG
{
static class Block
{
// A block has two elements
// as components
int value, localMax;
};
static class Stack
{
// Pointer of type block,
// Will be useful later as the
// size can be dynamically allocated
Block S[];
int size, top;
Stack(int n)
{
// Setting size of stack and
// initial value of top
size = n;
S = new Block[n];
for(int i=0;i<n;i++)S[i]=new Block();
top = -1;
}
// Function to push an element to the stack
void push(int n)
{
// Doesn't allow pushing elements
// if stack is full
if (top == size - 1)
{
System.out.print( "Stack is full" );
}
else
{
top++;
// If the inserted element is the first element
// then it is the maximum element, since no other
// elements is in the stack, so the localMax
// of the first element is the element itself
if (top == 0)
{
S[top].value = n;
S[top].localMax = n;
}
else
{
// If the newly pushed element is
// less than the localMax of element below it,
// Then the over all maximum doesn't change
// and hence, the localMax of the newly inserted
// element is same as element below it
if (S[top - 1].localMax > n)
{
S[top].value = n;
S[top].localMax = S[top - 1].localMax;
}
// Newly inserted element is greater than the localMax
// below it, hence the localMax of new element
// is the element itself
else
{
S[top].value = n;
S[top].localMax = n;
}
}
System.out.println( n + " inserted in stack" );
}
}
// Function to remove an element
// from the top of the stack
void pop()
{
// If stack is empty
if (top == -1)
{
System.out.println( "Stack is empty");
}
// Remove the element if the stack
// is not empty
else
{
top--;
System.out.println( "Element popped" );
}
}
// Function to find the maximum
// element from the stack
void max()
{
// If stack is empty
if (top == -1)
{
System.out.println( "Stack is empty");
}
else
{
// The overall maximum is the local maximum
// of the top element
System.out.println( "Maximum value in the stack: "+
S[top].localMax);
}
}
}
// Driver code
public static void main(String args[])
{
// Create stack of size 5
Stack S1=new Stack(5);
S1.push(2);
S1.max();
S1.push(6);
S1.max();
S1.pop();
S1.max();
}
}
// This code is contributed by Arnab Kundu
Python3
# Python3 implementation of the approach
class Block:
# A block has two elements
# as components (i.e. value and localMax)
def __init__(self, value, localMax):
self.value = value
self.localMax = localMax
class Stack:
def __init__(self, size):
# Setting size of stack and
# initial value of top
self.stack = [None] * size
self.size = size
self.top = -1
# Function to push an element
# to the stack
def push(self, value):
# Don't allow pushing elements
# if stack is full
if self.top == self.size - 1:
print("Stack is full")
else:
self.top += 1
# If the inserted element is the first element
# then it is the maximum element, since no other
# elements is in the stack, so the localMax
# of the first element is the element itself
if self.top == 0:
self.stack[self.top] = Block(value, value)
else:
# If the newly pushed element is less
# than the localMax of element below it,
# Then the over all maximum doesn't change
# and hence, the localMax of the newly inserted
# element is same as element below it
if self.stack[self.top - 1].localMax > value:
self.stack[self.top] = Block(
value, self.stack[self.top - 1].localMax)
# Newly inserted element is greater than
# the localMax below it, hence the localMax
# of new element is the element itself
else:
self.stack
self.stack[self.top] = Block(value, value)
print(value, "inserted in the stack")
# Function to remove an element
# from the top of the stack
def pop(self):
# If stack is empty
if self.top == -1:
print("Stack is empty")
# Remove the element if the stack
# is not empty
else:
self.top -= 1
print("Element popped")
# Function to find the maximum
# element from the stack
def max(self):
# If stack is empty
if self.top == -1:
print("Stack is empty")
else:
# The overall maximum is the local maximum
# of the top element
print("Maximum value in the stack:",
self.stack[self.top].localMax)
# Driver code
# Create stack of size 5
stack = Stack(5)
stack.push(2)
stack.max()
stack.push(6)
stack.max()
stack.pop()
stack.max()
# This code is contributed by girishthatte
C#
// C# implementation of the approach
using System;
class GFG
{
public class Block
{
// A block has two elements
// as components
public int value, localMax;
};
public class Stack
{
// Pointer of type block,
// Will be useful later as the
// size can be dynamically allocated
public Block []S;
public int size, top;
public Stack(int n)
{
// Setting size of stack and
// initial value of top
size = n;
S = new Block[n];
for(int i = 0; i < n; i++)S[i] = new Block();
top = -1;
}
// Function to push an element to the stack
public void push(int n)
{
// Doesn't allow pushing elements
// if stack is full
if (top == size - 1)
{
Console.Write( "Stack is full" );
}
else
{
top++;
// If the inserted element is the first element
// then it is the maximum element, since no other
// elements is in the stack, so the localMax
// of the first element is the element itself
if (top == 0)
{
S[top].value = n;
S[top].localMax = n;
}
else
{
// If the newly pushed element is
// less than the localMax of element below it,
// Then the over all maximum doesn't change
// and hence, the localMax of the newly inserted
// element is same as element below it
if (S[top - 1].localMax > n)
{
S[top].value = n;
S[top].localMax = S[top - 1].localMax;
}
// Newly inserted element is greater than the localMax
// below it, hence the localMax of new element
// is the element itself
else
{
S[top].value = n;
S[top].localMax = n;
}
}
Console.WriteLine( n + " inserted in stack" );
}
}
// Function to remove an element
// from the top of the stack
public void pop()
{
// If stack is empty
if (top == -1)
{
Console.WriteLine( "Stack is empty");
}
// Remove the element if the stack
// is not empty
else
{
top--;
Console.WriteLine( "Element popped" );
}
}
// Function to find the maximum
// element from the stack
public void max()
{
// If stack is empty
if (top == -1)
{
Console.WriteLine( "Stack is empty");
}
else
{
// The overall maximum is the local maximum
// of the top element
Console.WriteLine( "Maximum value in the stack: "+
S[top].localMax);
}
}
}
// Driver code
public static void Main(String []args)
{
// Create stack of size 5
Stack S1 = new Stack(5);
S1.push(2);
S1.max();
S1.push(6);
S1.max();
S1.pop();
S1.max();
}
}
// This code contributed by Rajput-Ji
JavaScript
<script>
/// JavaScript implementation of the approach
class Block{
/// A block has two elements
/// as components (i.e. value and localMax)
constructor(value, localMax){
this.value = value
this.localMax = localMax
}
}
class Stack{
constructor(size){
/// Setting size of stack and
/// initial value of top
this.stack = new Array(size).fill(null)
this.size = size
this.top = -1
}
// Function to push an element
// to the stack
push(value){
// Don't allow pushing elements
// if stack is full
if(this.top == this.size - 1)
document.write("Stack is full","</br>")
else{
this.top += 1
// If the inserted element is the first element
// then it is the maximum element, since no other
// elements is in the stack, so the localMax
// of the first element is the element itthis
if(this.top == 0)
this.stack[this.top] = new Block(value, value)
else{
// If the newly pushed element is less
// than the localMax of element below it,
// Then the over all maximum doesn't change
// and hence, the localMax of the newly inserted
// element is same as element below it
if(this.stack[this.top - 1].localMax > value){
this.stack[this.top] = new Block(
value, this.stack[this.top - 1].localMax)
}
// Newly inserted element is greater than
// the localMax below it, hence the localMax
// of new element is the element itthis
else{
this.stack[this.top] = new Block(value, value)
}
}
document.write(value, "inserted in the stack","</br>")
}
}
// Function to remove an element
// from the top of the stack
pop(){
// If stack is empty
if(this.top == -1)
document.write("Stack is empty","</br>")
// Remove the element if the stack
// is not empty
else{
this.top -= 1
document.write("Element popped","</br>")
}
}
// Function to find the maximum
// element from the stack
max(){
// If stack is empty
if(this.top == -1)
document.write("Stack is empty","</br>")
else{
// The overall maximum is the local maximum
// of the top element
document.write("Maximum value in the stack:",this.stack[this.top].localMax,"</br>")
}
}
}
// Driver code
// Create stack of size 5
let stack = new Stack(5)
stack.push(2)
stack.max()
stack.push(6)
stack.max()
stack.pop()
stack.max()
/// This code is contributed by shinjanpatra
</script>
Output: 2 inserted in stack
Maximum value in the stack: 2
6 inserted in stack
Maximum value in the stack: 6
Element popped
Maximum value in the stack: 2
Time Complexity : O(1)
Auxiliary Space: O(N)
Similar Reads
How to Create a Stack of Stack in C++? In C++, the stack is a container that follows the LIFO (Last In, First Out) order in which the elements are inserted and removed from it. In this article, we will learn how to create a stack of a stack in C++. Example:Input:Elements in stack1= 1, 2, 3, 4Elements in stack2= 5, 6, 7Output:Elements in
2 min read
Implement a Stack Using Vectors in C++ A stack is a data structure that follows the LIFO (Last In First Out) property means the element that is inserted at last will come out first whereas vectors are dynamic arrays. In this article, we will learn how to implement a stack using vectors in C++. Implementing a Stack Using Vectors in C++Vec
2 min read
How to Push an Element into Stack in C++? In C++ Stacks are a type of container adaptor with LIFO(Last In First Out) type of work, where a new element is added at one end (top) and an element is removed from that end only. In this article, we will learn to push the elements onto a Stack in C++. Example:Input:myStack = {40};Output:myStack: {
2 min read
C++ Program to Reverse a String Using Stack Given a string, reverse it using stack. For example "GeeksQuiz" should be converted to "ziuQskeeG". Following is simple algorithm to reverse a string using stack. 1) Create an empty stack.2) One by one push all characters of string to stack.3) One by one pop all characters from stack and put them ba
4 min read
How to Pop an Element From a Stack in C++? In C++, stacks are used to store a collection of similar types of data in a Last-In-First-Out (LIFO) manner. In this article, we will discuss how to pop an element from a stack in C++. Example:Input: myStack = {10, 34, 12, 90, 1}; Output: myStack = {10, 34, 12, 90};Removing an Element from a Stack i
2 min read