Implement Queue using Two Stacks

Implement Queue using Two Stacks

Welcome back to day 7 of the daily Leetcode series! After a very long time, the Leetcode gods have decided to bless us with a very simple, non-dynamic programming problem. Let's dive in, shall we?

Understanding the Problem

Here's the problem description:

Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (push, peek, pop, and empty).

Implement the MyQueue class:

  • void push(int x) Pushes element x to the back of the queue.

  • int pop() Removes the element from the front of the queue and returns it.

  • int peek() Returns the element at the front of the queue.

  • boolean empty() Returns true if the queue is empty, false otherwise.

Notes:

  • You must use only standard operations of a stack, which means only push to top, peek/pop from top, size, and is empty operations are valid.

  • Depending on your language, the stack may not be supported natively. You may simulate a stack using a list or deque (double-ended queue) as long as you use only a stack's standard operations.

Let's first understand what a queue and stack are.

A queue is a first-in-first-out data structure. It's similar to an array except for how elements are added and removed from it. Analogous to a queue in real life, the element that was inserted into the queue first is also removed first, hence the name FIFO (first-in-first-out) data structure.

A stack on the other hand is the opposite; it's a last-in-first-out (LIFO) structure. It is analogous to a stack of items in real life. The item that was added last, that is, the one on top of the stack is removed first.

Now that we have that cleared up, let's see how this problem can be solved.

Intuition

Our task is to use two stacks to simulate one queue. So, we have two data structures that support LIFO operations and we need to use those to simulate one data structure that supports FIFO operations.

The operations we need to perform are push() , pop(), peek() and empty() . Let's start with the push() operation.

push() Operation

Say you insert 3 elements in a queue and in a stack: 1,2 and 3. When you pop these elements from each of these data structures, you'll get them in the order 1,2,3 for the queue and 3,2,1 for the stack. Essentially, all we need to do is to reverse the order in which elements are popped from the stack in order to simulate a queue.

How do we achieve this? Remember, we have two stacks at our disposal. Let's go over the steps we need to perform in the push operation to make sure our stack acts like a queue.

We'll be using a stack s1 as our queue, and stack s2 as a utility structure. Take a look at the following code:

    void push(int x) {
        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        s1.push(x);
        while(!s2.empty()){
            s1.push(s2.top());
            s2.pop();
        }
    }

There are three steps that we perform here. One, when pushing an element to stack s1, if it is not empty, we first move all elements from s1 to s2. Then, we push the current element into s1. Then, we move all elements back from s2 to s1, thus maintaining a FIFO order among the elements.

Let's do a dry run to picture this process.

If this makes sense, let's move on to the next functions.

pop() Operation

This operation is fairly simple once we've implemented the push() operation. Since the elements will always be in FIFO order in the stack s1 , we only need to pop the first element in s1.

    int pop() {
        if(s1.empty()) return -1;
        int top = s1.top();
        s1.pop();
        return top;
    }

peek() Operation

The peek() operation returns the first element of the queue. In our case, it'll be the top element of stack s1.

    int peek() {
        int t = s1.top();
        return t;
    }

empty() Operation

This boolean function checks whether the queue is empty or not. Since we're treating s1 as our queue, we only need to check whether or not s1 is empty.

    bool empty() {
        if(s1.empty()) return true;
        return false;
    }

That's it for today! We had a very simple problem to solve today, let's hope that's not the case tomorrow! Please subscribe to my blog if you find these posts useful and want to be updated whenever I publish a new one.

Cheers!