Two Stacks in One Array

A Classic Interview Favourite

Share
Two Stacks in One Array
Photo by Avel Chuklanov / Unsplash

If you have sat through even a handful of coding interviews, you will notice that interviewers love problems that look simple but quietly test your fundamentals. "Implement two stacks using one array" is exactly that kind of problem.

It is a personal favourite of mine, and I have seen it asked again and again over the years. So let us sit together, understand the thinking behind it, and write clean code that you can confidently explain on the whiteboard.

The Problem

The statement is very short:

You are given a single array. Implement two stacks using only that one array, such that both stacks can grow and shrink independently.

Sounds easy, no? But here is the twist that makes people stumble — you cannot simply cut the array into two halves. If you split a size-10 array as 5 and 5, then what happens when the first stack needs 7 elements while the second one only needs 2? Stack one will overflow even though there is plenty of space lying empty on the other side. That is wasteful, and interviewers will immediately catch it.

So the real challenge is: use the space efficiently, so that one stack can borrow the room the other stack is not using.

The Core Idea

The trick is beautifully simple, and once you see it, you will never forget it.

Instead of dividing the array, let the two stacks grow towards each other from opposite ends:

  • Stack 1 starts from the left end (index 0) and grows to the right.
  • Stack 2 starts from the right end (index n-1) and grows to the left.
Stack 1 grows this way →
                        [ _ , _ , _ , _ , _ ]       
                                              ← Stack 2   grows this way

As long as the two "tops" have not crossed each other, there is still free space in the middle. This way, if Stack 1 is heavy and Stack 2 is light, Stack 1 automatically gets to use more of the array. No space is wasted. Beautiful utilisation.

The Implementation

Let us translate this idea into code. We keep two pointers — top1 for the left stack and top2 for the right stack.

class TwoStacks {
    constructor(n) {
        this.arr = new Array(n);
        this.top1 = -1;
        this.top2 = n;
    }

    push1(x) {
        this.top1++;
        this.arr[this.top1] = x;
    }

    push2(x) {
        this.top2--;
        this.arr[this.top2] = x;
    }

    pop1() {
        if (this.top1 < 0) {
            return -1;
        }
        let x = this.arr[this.top1];
        this.top1--;
        return x;
    }

    pop2() {
        if (this.top2 >= this.arr.length) {
            return -1;
        }
        let x = this.arr[this.top2];
        this.top2++;
        return x;
    }
}

let ts = new TwoStacks(5);
ts.push1(1);
ts.push2(2);
console.log(ts.pop1());

Walking Through the Code, Line by Line

Let us not just paste the code and run away. Let us actually understand what each pointer is doing, because that is what the interviewer really wants to hear.

The constructor:

this.top1 = -1;
this.top2 = n;

Notice these two starting values carefully. top1 starts at -1 because the left stack is empty and its first element will go at index 0 (after we increment). Similarly, top2 starts at n (one past the last valid index) because the right stack is empty and its first element will land at index n-1 (after we decrement). This little detail is the heart of the whole solution.

Pushing:

  • push1 moves top1 one step to the right, then places the value.
  • push2 moves top2 one step to the left, then places the value.

They are mirror images of each other — one increments, the other decrements. Simple and symmetric.

Popping:

  • pop1 first checks if (this.top1 < 0) — meaning the left stack is empty, so we return -1.
  • pop2 checks if (this.top2 >= this.arr.length) — meaning the right stack is empty, so again we return -1.

Then each one reads the top value, moves its pointer back, and returns the value.

The demo at the bottom:

ts.push1(1);   // Stack 1: 1 goes to index 0
ts.push2(2);   // Stack 2: 2 goes to index 4
console.log(ts.pop1());  // prints 1

Nice and clean. Stack 1 pushed 1 on the left, Stack 2 pushed 2 on the right, and popping Stack 1 returns 1. Exactly as expected.

One Important Point: The Overflow Check

Now, being your well-wisher, I must point out one thing that a sharp interviewer will definitely ask. In the code above, push1 and push2 do not check whether the array is full. If both stacks keep growing and the pointers cross each other (top1 + 1 === top2), then one stack will start overwriting the other stack's data. Big problem.

In a real answer, you should add an overflow guard like this:

push1(x) {
    if (this.top1 + 1 === this.top2) {
        return;   // no space left, overflow
    }
    this.top1++;
    this.arr[this.top1] = x;
}

push2(x) {
    if (this.top1 + 1 === this.top2) {
        return;   // no space left, overflow
    }
    this.top2--;
    this.arr[this.top2] = x;
}

The condition top1 + 1 === top2 simply means "the next free slot for Stack 1 is exactly where Stack 2 is sitting" — that is, the array is full. Mention this in your interview even if the basic version works; it shows maturity and that you think about edge cases. Interviewers love that.

Complexity

This is the part where this solution really shines:

  • Time: Every push and pop is O(1). Just pointer arithmetic, nothing more.
  • Space: O(n) for the single array, and — this is the beautiful part — zero wasted space. Whatever the array can hold, the two stacks together can fully use.

Final Thoughts

This problem is a wonderful reminder that the smartest solution is often not the most complicated one — it is the one that looks at the problem from a different angle. Instead of fighting over how to divide the array, we simply let the two stacks share it gracefully, each growing from its own end.

Keep this pattern in your back pocket. The same "two pointers moving towards each other" idea appears in many other problems too. Master it once, and you will start spotting it everywhere.

Happy coding, and all the best for your interviews!