Bird
Raised Fist0
Interview Prepstacks-monotonic-stackeasyAmazonBloomberg

Implement Stack Using Queues

Choose your preparation mode4 modes available
📋
Problem

Imagine you only have a queue data structure available, but you need to implement a stack for your application. How can you simulate the Last-In-First-Out behavior using First-In-First-Out operations?

Implement a last-in-first-out (LIFO) stack using only two queues or one queue. The implemented stack should support all the functions of a normal stack: push, pop, top, and empty. Implement the MyStack class: - void push(int x) Pushes element x onto the stack. - int pop() Removes the element on top of the stack and returns it. - int top() Returns the element on the top of the stack. - boolean empty() Returns true if the stack is empty, false otherwise. Notes: - You must use only standard operations of a queue, which means only push to back, peek/pop from front, size and is empty operations are valid. - Depending on the approach, you may use one or two queues.

1 ≤ x ≤ 10^5At most 10^5 calls will be made to push, pop, top, and empty.pop and top operations will always be called on non-empty stacks.
Edge cases: pop on stack with only one element → returns that element and stack becomes emptytop on stack with only one element → returns that element without removing itempty on newly created stack → returns true
</>
IDE
class MyStack: def __init__(self): pass def push(self, x: int) -> None: pass def pop(self) -> int: pass def top(self) -> int: pass def empty(self) -> bool: passclass MyStack { public MyStack() { } public void push(int x) { } public int pop() { return 0; } public int top() { return 0; } public boolean empty() { return false; } }class MyStack { public: MyStack() { } void push(int x) { } int pop() { return 0; } int top() { return 0; } bool empty() { return false; } };class MyStack { constructor() { } push(x) { } pop() { return 0; } top() { return 0; } empty() { return false; } }
class MyStack:
    def __init__(self):
        # Write your solution here
        pass
    def push(self, x: int) -> None:
        pass
    def pop(self) -> int:
        pass
    def top(self) -> int:
        pass
    def empty(self) -> bool:
        pass
class MyStack {
    public MyStack() {
        // Write your solution here
    }
    public void push(int x) {
    }
    public int pop() {
        return 0;
    }
    public int top() {
        return 0;
    }
    public boolean empty() {
        return false;
    }
}
#include <queue>
using namespace std;

class MyStack {
public:
    MyStack() {
        // Write your solution here
    }
    void push(int x) {
    }
    int pop() {
        return 0;
    }
    int top() {
        return 0;
    }
    bool empty() {
        return false;
    }
};
class MyStack {
    constructor() {
        // Write your solution here
    }
    push(x) {
    }
    pop() {
        return 0;
    }
    top() {
        return 0;
    }
    empty() {
        return false;
    }
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: pop returns elements in FIFO order instead of LIFOPush operation does not rotate the queue after enqueue, so the oldest element is popped first.✅ After enqueueing new element in push, rotate the queue by dequeuing and enqueuing all previous elements once.
Wrong: top returns wrong element after multiple popsTop operation returns last element enqueued instead of front of queue after rotation.✅ Ensure push rotates queue so that the top element is always at the front; top returns front element.
Wrong: empty returns false on new stackEmpty method does not check if internal queue is empty properly.✅ Implement empty() by checking if the queue size is zero.
Wrong: pop or top fails on single element stackPop or top does not handle single element queue correctly, possibly causing errors or wrong returns.✅ Handle single element queue case explicitly or ensure queue operations work correctly for size one.
Wrong: TLE on large inputPush operation implemented with nested loops or inefficient queue operations causing O(n^2) or worse complexity.✅ Use efficient queue rotation with O(n) per push and O(1) pop/top; avoid nested loops.
✓
Test Cases
t1_01basic
Input["push(1)","push(2)","top()","pop()","empty()"]
Expected[2,2,false]

After pushing 1 and 2, the top is 2. Popping removes 2. The stack is not empty after popping 2.

t1_02basic
Input["push(3)","push(4)","top()","pop()","top()","empty()"]
Expected[4,4,3,false]

Push 3 then 4; top is 4; pop removes 4; new top is 3; stack is not empty.

t2_01edge
Input["empty()"]
Expected[true]

Newly created stack is empty.

t2_02edge
Input["push(10)","top()","pop()","empty()"]
Expected[10,10,true]

Stack with one element returns that element on top and pop; becomes empty after pop.

t2_03edge
Input["push(5)","push(5)","top()","pop()","top()","pop()","empty()"]
Expected[5,5,5,true]

Multiple identical elements pushed; top and pop behave correctly with duplicates.

t3_01corner
Input["push(1)","push(2)","push(3)","pop()","pop()","top()","empty()"]
Expected[3,2,1,false]

Test correct LIFO order after multiple pushes and pops.

t3_02corner
Input["push(1)","pop()","push(2)","top()","pop()","empty()"]
Expected[1,2,2,true]

Test push-pop-push sequence to ensure stack state resets correctly.

t3_03corner
Input["push(1)","push(2)","push(3)","top()","pop()","top()","pop()","top()","pop()","empty()"]
Expected[3,3,2,2,1,1,true]

Greedy trap test: ensure no shortcut that assumes pop is O(1) without rotation.

t4_01performance
Input["push(1)","push(2)","push(3)","push(4)","push(5)","push(6)","push(7)","push(8)","push(9)","push(10)","push(11)","push(12)","push(13)","push(14)","push(15)","push(16)","push(17)","push(18)","push(19)","push(20)","push(21)","push(22)","push(23)","push(24)","push(25)","push(26)","push(27)","push(28)","push(29)","push(30)","push(31)","push(32)","push(33)","push(34)","push(35)","push(36)","push(37)","push(38)","push(39)","push(40)","push(41)","push(42)","push(43)","push(44)","push(45)","push(46)","push(47)","push(48)","push(49)","push(50)","push(51)","push(52)","push(53)","push(54)","push(55)","push(56)","push(57)","push(58)","push(59)","push(60)","push(61)","push(62)","push(63)","push(64)","push(65)","push(66)","push(67)","push(68)","push(69)","push(70)","push(71)","push(72)","push(73)","push(74)","push(75)","push(76)","push(77)","push(78)","push(79)","push(80)","push(81)","push(82)","push(83)","push(84)","push(85)","push(86)","push(87)","push(88)","push(89)","push(90)","push(91)","push(92)","push(93)","push(94)","push(95)","push(96)","push(97)","push(98)","push(99)","push(100)","top()","pop()","empty()"]
⏱ Performance - must finish in 2000ms

Performance test with n=100 pushes followed by top, pop, empty. O(n) push with queue rotation must complete within 2 seconds.

Practice

(1/5)
1. Given the following Python code for asteroid collision, what is the output when the input is [8, -8, 5, -10]?
def asteroidCollision(asteroids):
    stack = []
    for a in asteroids:
        alive = True
        while alive and stack and stack[-1] > 0 and a < 0:
            if stack[-1] < -a:
                stack.pop()
            elif stack[-1] == -a:
                stack.pop()
                alive = False
            else:
                alive = False
        if alive:
            stack.append(a)
    return stack

print(asteroidCollision([8, -8, 5, -10]))
easy
A. [5, -10]
B. [-10]
C. [8, 5, -10]
D. []

Solution

  1. Step 1: Trace collision between 8 and -8

    8 and -8 are equal size but opposite direction, both explode -> stack empty.
  2. Step 2: Process 5 and then -10

    5 is pushed; -10 collides with 5, since 10 > 5, 5 pops, -10 remains and is pushed.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Final stack contains only [-10] after resolving collisions [OK]
Hint: Equal size opposite asteroids both explode [OK]
Common Mistakes:
  • Forgetting to pop both equal asteroids
  • Appending asteroid after it exploded
  • Not handling multiple collisions in while loop
2. Consider the following Python function that computes the largest rectangle area in a histogram using a monotonic stack approach. Given the input heights = [2, 1, 5], what is the value of the variable right after computing the right boundaries (just before calculating max_area)?
easy
A. [1, 2, 3]
B. [1, 3, 2]
C. [1, 3, 3]
D. [3, 3, 3]

Solution

  1. Step 1: Trace right boundary computation for i=2 (height=5)

    Stack is empty, so right[2] = n = 3, stack = [2]
  2. Step 2: Trace i=1 (height=1)

    Pop indices with height >= 1: pop 2 (height=5), stack empty, right[1] = 3, stack = [1]
  3. Step 3: Trace i=0 (height=2)

    Stack top is 1 (height=1) < 2, so right[0] = 1, stack = [1,0]
  4. Final Answer:

    Option B -> Option B
  5. Quick Check:

    Right boundaries correctly reflect next smaller bar indices [OK]
Hint: Right boundaries found by scanning from right with stack [OK]
Common Mistakes:
  • Confusing indices or off-by-one in right boundary
  • Not clearing stack before right boundary pass
3. Consider the following MinStack implementation using a single stack with encoded minimums. After executing the sequence push(3), push(5), push(2), pop(), what is the value returned by getMin()?
easy
A. None
B. 3
C. 5
D. 2

Solution

  1. Step 1: Trace push(3)

    Stack empty, push 0, minVal=3.
  2. Step 2: Trace push(5)

    diff=5-3=2>0, push 2, minVal=3.
  3. Step 3: Trace push(2)

    diff=2-3=-1<0, push -1, minVal=2.
  4. Step 4: Trace pop()

    pop -1 (negative), minVal=2 - (-1)=3.
  5. Step 5: getMin()

    minVal=3.
  6. Final Answer:

    Option B -> Option B
  7. Quick Check:

    After popping 2, min is restored to 3 [OK]
Hint: Negative diff updates minVal on push and pop [OK]
Common Mistakes:
  • Forgetting to update minVal on pop
  • Returning old minVal after pop
  • Confusing top value with minVal
4. Consider the following buggy code for asteroid collision. Which line contains the subtle bug that causes incorrect behavior on equal size asteroids?
def asteroidCollision(asteroids):
    stack = []
    for a in asteroids:
        alive = True
        while alive and stack and stack[-1] > 0 and a < 0:
            if stack[-1] < -a:
                stack.pop()
            elif stack[-1] == -a:
                alive = False
            else:
                alive = False
        if alive:
            stack.append(a)
    return stack
medium
A. Line with 'stack.pop()' inside 'if stack[-1] < -a:'
B. Line with 'while alive and stack and stack[-1] > 0 and a < 0:' condition
C. Line with 'alive = False' inside 'elif stack[-1] == -a:'
D. Line with 'stack.append(a)' after the while loop

Solution

  1. Step 1: Identify behavior on equal size asteroids

    When sizes are equal, both asteroids should explode (pop from stack and not append current).
  2. Step 2: Check code for equal size case

    In the buggy code, stack.pop() is missing when sizes are equal, so the top asteroid remains incorrectly.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Missing stack.pop() causes incorrect survival of equal asteroid [OK]
Hint: Equal size asteroids both must be removed [OK]
Common Mistakes:
  • Forgetting to pop stack on equal size
  • Appending asteroid after it exploded
  • Incorrect while loop condition
5. What is the time complexity of the optimized monotonic stack solution for the Next Greater Element I problem, where m = length of nums1 and n = length of nums2?
medium
A. O(m * n) because for each element in nums1, we scan nums2 to find the next greater element.
B. O(n) because only nums2 is processed with a stack; nums1 lookup is constant time.
C. O(n + m) because each element in nums2 is pushed and popped at most once, and mapping results for nums1 is O(m).
D. O(n log n) due to sorting nums2 before processing.

Solution

  1. Step 1: Analyze stack operations on nums2

    Each element in nums2 is pushed once and popped at most once, so stack operations are O(n).
  2. Step 2: Analyze mapping and lookup for nums1

    Mapping next greater elements for nums1 uses a hashmap and set lookups, each O(1), done m times, total O(m).
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Combined complexity is O(n + m), not O(m*n) or O(n log n) [OK]
Hint: Stack operations are linear; hashmap lookups are constant [OK]
Common Mistakes:
  • Assuming nested loops cause O(m*n) complexity
  • Confusing sorting-based approaches with stack-based ones
  • Ignoring the cost of hashmap lookups
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard