Bird
Raised Fist0
DSA Javascriptprogramming

Queue Using Two Stacks in DSA Javascript

Choose your learning style10 modes available
Mental Model
Use two stacks to mimic a queue's order by reversing elements twice. One stack holds incoming items, the other reverses order for removal.
Analogy: Imagine two trays of plates. You stack plates on the first tray. When you want to serve the oldest plate, you flip all plates onto the second tray, reversing their order, so the oldest plate is on top.
stack1: top -> [ ] bottom
stack2: top -> [ ] bottom
queue: empty
Dry Run Walkthrough
Input: enqueue 1, enqueue 2, dequeue, enqueue 3, dequeue
Goal: Show how two stacks work together to behave like a queue with FIFO order
Step 1: enqueue 1: push 1 onto stack1
stack1: [1]
stack2: []
Why: New elements go to stack1 to keep insertion order
Step 2: enqueue 2: push 2 onto stack1
stack1: [1, 2] (top is 2)
stack2: []
Why: Keep adding new elements on top of stack1
Step 3: dequeue: stack2 empty, move all from stack1 to stack2 reversing order
stack1: []
stack2: [2, 1] (top is 1)
Why: Reversing stack1 to stack2 makes oldest element accessible on top
Step 4: dequeue: pop from stack2 (remove 1)
stack1: []
stack2: [2]
Why: Pop oldest element from stack2 to simulate queue dequeue
Step 5: enqueue 3: push 3 onto stack1
stack1: [3]
stack2: [2]
Why: New elements always go to stack1
Step 6: dequeue: stack2 not empty, pop from stack2 (remove 2)
stack1: [3]
stack2: []
Why: Pop from stack2 if not empty to maintain queue order
Result:
stack1: [3]
stack2: []
queue order after operations: 3 is next to dequeue
Annotated Code
DSA Javascript
class QueueUsingTwoStacks {
  constructor() {
    this.stack1 = [];
    this.stack2 = [];
  }

  enqueue(value) {
    this.stack1.push(value); // add new element to stack1
  }

  dequeue() {
    if (this.stack2.length === 0) {
      while (this.stack1.length > 0) {
        this.stack2.push(this.stack1.pop()); // move all from stack1 to stack2 reversing order
      }
    }
    if (this.stack2.length === 0) {
      return null; // queue empty
    }
    return this.stack2.pop(); // pop from stack2 to dequeue
  }

  printQueue() {
    // To print queue order, combine stack2 reversed + stack1
    const stack2Reversed = [...this.stack2].reverse();
    const queueOrder = stack2Reversed.concat(this.stack1);
    return queueOrder.join(' -> ') + ' -> null';
  }
}

// Driver code
const queue = new QueueUsingTwoStacks();
queue.enqueue(1);
queue.enqueue(2);
console.log(queue.dequeue()); // should print 1
queue.enqueue(3);
console.log(queue.dequeue()); // should print 2
console.log(queue.printQueue()); // should print 3 -> null
this.stack1.push(value); // add new element to stack1
push new element to stack1 to keep insertion order
if (this.stack2.length === 0) { while (this.stack1.length > 0) { this.stack2.push(this.stack1.pop()); } }
if stack2 empty, move all elements from stack1 to stack2 reversing order
return this.stack2.pop(); // pop from stack2 to dequeue
pop oldest element from stack2 to simulate queue dequeue
OutputSuccess
1 2 3 -> null
Complexity Analysis
Time: O(1) amortized per operation because each element moves between stacks at most once
Space: O(n) because all elements are stored in two stacks combined
vs Alternative: Compared to a simple queue using an array where dequeue is O(n) due to shifting, this approach achieves amortized O(1) dequeue by using two stacks
Edge Cases
dequeue from empty queue
returns null indicating queue is empty
DSA Javascript
if (this.stack2.length === 0) { return null; }
enqueue then dequeue immediately
correctly returns the enqueued element
DSA Javascript
this.stack1.push(value);
multiple enqueues before any dequeue
all elements stored in stack1 until first dequeue triggers transfer
DSA Javascript
while (this.stack1.length > 0) { this.stack2.push(this.stack1.pop()); }
When to Use This Pattern
When you need a queue but only have stack operations, use two stacks to reverse order twice and simulate FIFO behavior.
Common Mistakes
Mistake: Not transferring elements from stack1 to stack2 when stack2 is empty before dequeue
Fix: Add a check to move all elements from stack1 to stack2 only when stack2 is empty
Mistake: Popping from stack1 directly on dequeue
Fix: Always pop from stack2 after transferring elements to maintain correct order
Summary
Implements a queue using two stacks by reversing element order twice.
Use when you want queue behavior but only have stack operations available.
The key insight is that reversing twice restores the original order, enabling FIFO with stacks.

Practice

(1/5)
1. What is the main idea behind implementing a Queue using two stacks?
easy
A. Use two stacks to reverse the order twice to maintain queue order
B. Use one stack for enqueue and another for dequeue operations
C. Use two stacks to store elements in sorted order
D. Use one stack to hold even numbers and another for odd numbers

Solution

  1. Step 1: Understand queue order

    A queue follows FIFO (First In First Out), so the first element added should be the first removed.
  2. Step 2: Use two stacks to reverse order twice

    One stack reverses the order when pushing elements, and the second stack reverses it back when popping, preserving FIFO.
  3. Final Answer:

    Use two stacks to reverse the order twice to maintain queue order -> Option A
  4. Quick Check:

    Two stacks reverse order twice = Queue order [OK]
Hint: Two reversals with stacks keep queue order intact [OK]
Common Mistakes:
  • Thinking one stack alone can maintain queue order
  • Confusing stack sorting with queue behavior
  • Using stacks for odd/even separation incorrectly
2. Which of the following is the correct syntax to push an element x onto a stack named stack1 in JavaScript?
easy
A. stack1.push(x);
B. stack1.add(x);
C. stack1.insert(x);
D. stack1.enqueue(x);

Solution

  1. Step 1: Recall JavaScript stack push method

    JavaScript arrays use push() to add elements at the end, simulating stack push.
  2. Step 2: Verify other options

    add(), insert(), and enqueue() are not valid array methods for pushing.
  3. Final Answer:

    stack1.push(x); -> Option A
  4. Quick Check:

    Array push method = stack1.push(x) [OK]
Hint: Use push() to add elements to stack in JavaScript [OK]
Common Mistakes:
  • Using enqueue() which is for queues, not stacks
  • Using add() or insert() which are not JavaScript array methods
  • Confusing stack push with queue enqueue
3. What will be the output of the following code snippet implementing a queue using two stacks?
class QueueTwoStacks {
  constructor() {
    this.stack1 = [];
    this.stack2 = [];
  }
  enqueue(x) {
    this.stack1.push(x);
  }
  dequeue() {
    if (this.stack2.length === 0) {
      while (this.stack1.length > 0) {
        this.stack2.push(this.stack1.pop());
      }
    }
    return this.stack2.pop();
  }
}

const q = new QueueTwoStacks();
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);
console.log(q.dequeue());
q.enqueue(40);
console.log(q.dequeue());
medium
A. 20 30
B. 30 40
C. 10 30
D. 10 20

Solution

  1. Step 1: Trace enqueue operations

    Elements 10, 20, 30 are pushed into stack1 in order: [10, 20, 30].
  2. Step 2: Trace first dequeue

    stack2 is empty, so pop all from stack1 to stack2: stack2 becomes [30, 20, 10]. Then pop from stack2 returns 10.
  3. Step 3: Enqueue 40 and second dequeue

    40 is pushed to stack1: [40]. stack2 still has [30, 20]. Dequeue pops from stack2 returning 20.
  4. Final Answer:

    10 20 -> Option D
  5. Quick Check:

    FIFO order maintained: 10 then 20 dequeued [OK]
Hint: Dequeue empties stack2 first, then pops top [OK]
Common Mistakes:
  • Assuming dequeue pops directly from stack1
  • Not transferring all elements to stack2 before dequeue
  • Mixing order of elements after transfer
4. Identify the bug in this dequeue method of a queue implemented using two stacks:
dequeue() {
  while (this.stack1.length > 0) {
    this.stack2.push(this.stack1.pop());
  }
  return this.stack2.pop();
}
medium
A. It pops from stack1 instead of stack2
B. It never transfers elements from stack1 to stack2
C. It empties stack1 every dequeue without checking if stack2 is empty
D. It returns undefined always

Solution

  1. Step 1: Analyze the transfer logic

    The method transfers all elements from stack1 to stack2 every time dequeue is called, without checking if stack2 is empty.
  2. Step 2: Understand consequence

    This causes new elements to be appended to stack2 (which may have remaining older elements), violating FIFO as new elements are popped before older ones.
  3. Final Answer:

    It empties stack1 every dequeue without checking if stack2 is empty -> Option C
  4. Quick Check:

    Transfer only if stack2.length === 0 [OK]
Hint: Transfer only when stack2 is empty to keep elements safe [OK]
Common Mistakes:
  • Transferring elements every dequeue call
  • Not checking if stack2 is empty before transfer
  • Confusing which stack to pop from
5. You want to implement a queue using two stacks where enqueue and dequeue operations are both efficient. Which approach below achieves amortized O(1) time per operation?
hard
A. Push elements alternately to stack1 and stack2 on enqueue; pop from stack1 on dequeue
B. Push all elements to stack1 on enqueue; transfer to stack2 only when stack2 is empty during dequeue
C. Push elements to stack1 and stack2 simultaneously on enqueue; pop from stack2 on dequeue
D. Push all elements to stack2 on enqueue; pop from stack1 on dequeue

Solution

  1. Step 1: Understand amortized O(1) with two stacks

    Enqueue pushes to stack1 only. Dequeue pops from stack2. Transfer happens only when stack2 is empty, moving all elements from stack1 to stack2.
  2. Step 2: Analyze other options

    Alternating pushes or pushing to both stacks simultaneously breaks queue order or wastes operations. Pushing all to stack2 and popping from stack1 is incorrect.
  3. Final Answer:

    Push all elements to stack1 on enqueue; transfer to stack2 only when stack2 is empty during dequeue -> Option B
  4. Quick Check:

    Lazy transfer on dequeue = amortized O(1) [OK]
Hint: Transfer only when needed during dequeue for efficiency [OK]
Common Mistakes:
  • Transferring elements on every enqueue or dequeue
  • Pushing to both stacks simultaneously
  • Ignoring stack2 emptiness check before transfer
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