Open In App

Find maximum in a stack in O(1) time and O(1) extra space

Last Updated : 25 Feb, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a stack of integers. The task is to design a special stack such that the maximum element can be found in O(1) time and O(1) extra space.

Examples

Input: operations = [push(2), push(3), peek(), pop(), getMax(), push(1), getMax()]
Output: [3, 2, 2]
Explanation:
push(2): Stack is [2]
push(3): Stack is [2, 3]
peek(): Top element is 3
pop(): Removes 3, stack is [2]
getMax(): Maximum element is 2
push(1): Stack is [2, 1]
getMax(): Maximum element is 2

Input: operations = [push(10), getMax(), push(5), getMax(), pop()]
Output: [10, 5]
Explanation:
push(10): Stack is [10]
getMax(): Maximum element is 10
push(5): Stack is [10, 5]
getMax(): Maximum element is 10
pop(): Removes 5, stack is [10]

Approach:

The idea behind this approach is to use a transformation to encode the previous maximum when a new maximum is pushed onto the stack. By storing (2 * x - maxEle) for new maximums, we retain information about the old maximum in the stack.
During a pop operation, if the popped value represents a transformed maximum, we can restore the previous maximum using the formula maxEle = 2 * maxEle - y.

Push Operation

  • When the stack is empty, we insert the given element x into the stack and set maxEle (the variable storing the current maximum element) to x.
  • Otherwise, we compare the new element x with maxEle. If x ≤ maxEle, simply insert x into the stack. The maximum element remains unchanged. If x > maxEle, the stack does not store x directly. Instead, it stores a modified value calculated as (2 * x - maxEle). Then, maxEle is updated to x.

Pop Operation

Remove the top element of the stack and check its relationship with maxEle:

  • If the top element y ≤ maxEle, simply remove it. The maximum element remains unchanged.
  • If y > maxEle, it indicates that y was a placeholder value (not an actual element in the stack). To retrieve the previous maximum, update maxEle using the formula (2 * maxEle - y). This operation restores the value of the previous maximum.

Why the Equations Work?

The equations maintain the relationship between the stack's maximum element and the actual stack contents.

  • When pushing an element, if it’s greater than maxEle, the modified value (2 * x - maxEle) is stored. This value is always greater than the previous maxEle.
  • When popping a placeholder value, the previous maximum is recalculated as (2 * maxEle - y).

This ensures that the stack doesn’t store the actual maximum value when x exceeds maxEle, and the maximum value is always tracked using maxEle.

Push Operations:

  • Push 3: Stack = [3], maxEle = 3.
  • Push 5: Since 5 > maxEle, store 7 (2*5 - 3) in the stack and update maxEle to 5. Stack = [3, 7].
  • Push 2: Since 2 ≤ maxEle, insert 2 into the stack. Stack = [3, 7, 2]. maxEle = 5.
  • Push 1: Since 1 ≤ maxEle, insert 1 into the stack. Stack = [3, 7, 2, 1]. maxEle = 5.

Pop Operations:

  • Pop 1: Since 1 ≤ maxEle, remove 1. Stack = [3, 7, 2]. maxEle = 5.
  • Pop 2: Since 2 ≤ maxEle, remove 2. Stack = [3, 7]. maxEle = 5.
  • Pop 7: Since 7 > maxEle, retrieve original maxEle (5) and update maxEle to 2*5 - 7 = 3. Stack = [3]. maxEle = 3.

Below is the implementation of the above approach:

C++
// C++ program to implement a stack that find
// maximum in stack in O(1) time and space.
#include <iostream>
#include <stack>
using namespace std;

// Class to implement a stack with getMax()
class MaxStack {
  private:
    stack<int> s;
    int maxEle;

  public:
    MaxStack() { 
        maxEle = -1; 
    }

    // Add an element to the top of Stack
    void push(int x) {
        if (s.empty()) {
            maxEle = x;
            s.push(x);
        }
        // If new number is greater than maxEle
        else if (x > maxEle) {
            s.push(2 * x - maxEle);
            maxEle = x;
        } else {
            s.push(x);
        }
    }

    // Remove the top element from the Stack
    void pop() {
        if (s.empty()) {
            return;
        }

        int top = s.top();
        s.pop();

        // Maximum will change if the maximum element
        // of the stack is being removed.
        if (top > maxEle) {
            maxEle = 2 * maxEle - top;
        }
    }

    // Returns top element of the Stack
    int peek() {
        if (s.empty()) {
            return -1;
        }

        int top = s.top();

        // If maxEle < top means maxEle stores value of top.
        return (maxEle < top) ? maxEle : top;
    }

    // Finds maximum element of Stack
    int getMax() {
        if (s.empty())
            return -1;

        // variable maxEle stores the maximum element
        // in the stack
        return maxEle;
    }
};

int main() {
    MaxStack stk;
    
    stk.push(2); 
    stk.push(3);
    cout << stk.peek() << " ";
    stk.pop();
    cout << stk.getMax() << " ";
    stk.push(1);
    cout << stk.getMax() << " ";

    return 0;
}
Java
// Java program to implement a stack that find
// maximum in stack in O(1) time and space.
import java.util.Stack;

// Class to implement a stack with getMax()
class MaxStack {
    private Stack<Integer> s;
    private int maxEle;

    public MaxStack() {
        s = new Stack<>();
        maxEle = -1;
    }

    // Add an element to the top of Stack
    public void push(int x) {
        if (s.isEmpty()) {
            maxEle = x;
            s.push(x);
        }
        // If new number is greater than maxEle
        else if (x > maxEle) {
            s.push(2 * x - maxEle);
            maxEle = x;
        } else {
            s.push(x);
        }
    }

    // Remove the top element from the Stack
    public void pop() {
        if (s.isEmpty()) {
            return;
        }

        int top = s.pop();

        // Maximum will change if the maximum element
        // of the stack is being removed.
        if (top > maxEle) {
            maxEle = 2 * maxEle - top;
        }
    }

    // Returns top element of the Stack
    public int peek() {
        if (s.isEmpty()) {
            return -1;
        }

        int top = s.peek();

        // If maxEle < top means maxEle stores value of top.
        return (maxEle < top) ? maxEle : top;
    }

    // Finds maximum element of Stack
    public int getMax() {
        if (s.isEmpty()) {
            return -1;
        }

        // variable maxEle stores the maximum element
        // in the stack
        return maxEle;
    }

    public static void main(String[] args) {
        MaxStack stk = new MaxStack();

        stk.push(2);
        stk.push(3);
        System.out.print(stk.peek() + " ");
        stk.pop();
        System.out.print(stk.getMax() + " ");
        stk.push(1);
        System.out.print(stk.getMax() + " ");
    }
}
Python
# Python program to implement a stack that finds
# maximum in stack in O(1) time and space.

# Class to implement a stack with getMax()
class MaxStack:
    def __init__(self):
        self.s = []
        self.maxEle = -1

    # Add an element to the top of Stack
    def push(self, x):
        if not self.s:
            self.maxEle = x
            self.s.append(x)
        # If new number is greater than maxEle
        elif x > self.maxEle:
            self.s.append(2 * x - self.maxEle)
            self.maxEle = x
        else:
            self.s.append(x)

    # Remove the top element from the Stack
    def pop(self):
        if not self.s:
            return

        top = self.s.pop()

        # Maximum will change if the maximum element
        # of the stack is being removed.
        if top > self.maxEle:
            self.maxEle = 2 * self.maxEle - top

    # Returns top element of the Stack
    def peek(self):
        if not self.s:
            return -1

        top = self.s[-1]

        # If maxEle < top means maxEle stores value of top.
        return self.maxEle if self.maxEle < top else top

    # Finds maximum element of Stack
    def getMax(self):
        if not self.s:
            return -1

        # variable maxEle stores the maximum element
        # in the stack
        return self.maxEle


if __name__ == "__main__":
    stk = MaxStack()

    stk.push(2)
    stk.push(3)
    print(stk.peek(), end=" ")
    stk.pop()
    print(stk.getMax(), end=" ")
    stk.push(1)
    print(stk.getMax(), end=" ")
C#
// C# program to implement a stack that find
// maximum in stack in O(1) time and space.

using System;
using System.Collections.Generic;

// Class to implement a stack with getMax()
class MaxStack {
    private Stack<int> s;
    private int maxEle;

    public MaxStack() {
        s = new Stack<int>();
        maxEle = -1;
    }

    // Add an element to the top of Stack
    public void Push(int x) {
        if (s.Count == 0) {
            maxEle = x;
            s.Push(x);
        }
        // If new number is greater than maxEle
        else if (x > maxEle) {
            s.Push(2 * x - maxEle);
            maxEle = x;
        } else {
            s.Push(x);
        }
    }

    // Remove the top element from the Stack
    public void Pop() {
        if (s.Count == 0) {
            return;
        }

        int top = s.Pop();

        // Maximum will change if the maximum element
        // of the stack is being removed.
        if (top > maxEle) {
            maxEle = 2 * maxEle - top;
        }
    }

    // Returns top element of the Stack
    public int Peek() {
        if (s.Count == 0) {
            return -1;
        }

        int top = s.Peek();

        // If maxEle < top means maxEle stores value of top.
        return (maxEle < top) ? maxEle : top;
    }

    // Finds maximum element of Stack
    public int GetMax() {
        if (s.Count == 0) {
            return -1;
        }

        // variable maxEle stores the maximum element
        // in the stack
        return maxEle;
    }

    public static void Main() {
        MaxStack stk = new MaxStack();

        stk.Push(2);
        stk.Push(3);
        Console.Write(stk.Peek() + " ");
        stk.Pop();
        Console.Write(stk.GetMax() + " ");
        stk.Push(1);
        Console.Write(stk.GetMax() + " ");
    }
}
JavaScript
// JavaScript program to implement a stack that finds
// maximum in stack in O(1) time and space.

// Class to implement a stack with getMax()
class MaxStack {
    constructor() {
        this.s = [];
        this.maxEle = -1;
    }

    // Add an element to the top of Stack
    push(x) {
        if (this.s.length === 0) {
            this.maxEle = x;
            this.s.push(x);
        }
        // If new number is greater than maxEle
        else if (x > this.maxEle) {
            this.s.push(2 * x - this.maxEle);
            this.maxEle = x;
        } else {
            this.s.push(x);
        }
    }

    // Remove the top element from the Stack
    pop() {
        if (this.s.length === 0) {
            return;
        }

        let top = this.s.pop();

        // Maximum will change if the maximum element
        // of the stack is being removed.
        if (top > this.maxEle) {
            this.maxEle = 2 * this.maxEle - top;
        }
    }

    // Returns top element of the Stack
    peek() {
        if (this.s.length === 0) {
            return -1;
        }

        let top = this.s[this.s.length - 1];

        // If maxEle < top means maxEle stores value of top.
        return this.maxEle < top ? this.maxEle : top;
    }

    // Finds maximum element of Stack
    getMax() {
        if (this.s.length === 0) {
            return -1;
        }

        // variable maxEle stores the maximum element
        // in the stack
        return this.maxEle;
    }
}

// Driver Code
const stk = new MaxStack();

stk.push(2);
stk.push(3);
console.log(stk.peek(), " ");
stk.pop();
console.log(stk.getMax(), " ");
stk.push(1);
console.log(stk.getMax(), " ");

Output
3 2 2 

How does this approach work? 

When the element to be inserted is more than maxEle, we insert “2x – maxEle”. The important thing to note is, that 2x – maxEle will always be more than x (proved below), i.e., new maxEle and while popping out this element we will see that something unusual has happened as the popped element is less than the maxEle. So we will be updating maxEle.

How 2*x – maxEle is more than x in push()? 

x > maxEle which means x – maxEle > 0 

// Adding x on both sides
x – maxEle + x > 0 + x 
2*x – maxEle > x 
We can conclude 2*x – maxEle > new maxEle 

While popping out, if we find the element(y) more than the current maxEle, we find the new maxEle = 2*maxEle – y

How previous max element, prevMaxEle is, 2*maxEle – y
in pop() is y the popped element?

 // We pushed y as 2x – prevMaxEle. Here 
// prevMaxEle is maxEle before y was inserted

y = 2*x – prevMaxEle  

// Value of maxEle was made equal to x
maxEle = x

new maxEle = 2 * maxEle – y 
                   = 2*x – (2*x – prevMaxEle)
                   = prevMaxEle // This is what we wanted

Time Complexity: O(1), as all these operations are constant-time due to direct stack manipulation and comparisons. 
Auxiliary Space: O(1), as we use only a fixed amount of extra space (for maxEle).


Next Article

Similar Reads