Bird
Raised Fist0
DSA Typescriptprogramming

Queue Using Two Stacks in DSA Typescript

Choose your learning style10 modes available
Mental Model
A queue can be made using two stacks by reversing the order twice to keep the first-in-first-out order.
Analogy: Imagine two trays where you stack plates. You put plates on the first tray, then to serve the oldest plate, you flip all plates onto the second tray, reversing their order, so the oldest plate is on top to take out first.
stack1: top -> []
stack2: top -> []
queue front is top of stack2 if not empty, else bottom of stack1
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]
stack2: []
Why: Keep adding new elements on top of stack1
Step 3: dequeue: stack2 empty, move all from stack1 to stack2 reversing order, pop top of stack2 (1)
stack1: []
stack2: [2]
Why: Transfer from stack1 to stack2 reverses order so oldest element (1) is on top, then pop it
Step 4: enqueue 3: push 3 onto stack1
stack1: [3]
stack2: [2]
Why: New elements always go to stack1
Step 5: dequeue: pop top of stack2 (2)
stack1: [3]
stack2: []
Why: Continue removing from stack2 if not empty
Result:
stack1: [3]
stack2: []
Dequeued elements in order: 1, 2
Annotated Code
DSA Typescript
class QueueUsingTwoStacks {
  private stack1: number[] = [];
  private stack2: number[] = [];

  enqueue(value: number): void {
    // Push new element onto stack1
    this.stack1.push(value);
  }

  dequeue(): number | null {
    // If stack2 is empty, move all elements from stack1 to stack2
    if (this.stack2.length === 0) {
      while (this.stack1.length > 0) {
        // Pop from stack1 and push onto stack2 to reverse order
        this.stack2.push(this.stack1.pop()!);
      }
    }
    // Pop from stack2 if not empty
    if (this.stack2.length === 0) {
      return null; // Queue is empty
    }
    return this.stack2.pop()!;
  }

  printQueue(): void {
    // Print elements in queue order
    const result: number[] = [];
    // Elements in stack2 are in correct dequeue order
    for (let i = this.stack2.length - 1; i >= 0; i--) {
      result.push(this.stack2[i]);
    }
    // Elements in stack1 are in enqueue order, so print from bottom to top
    for (let i = 0; i < this.stack1.length; i++) {
      result.push(this.stack1[i]);
    }
    console.log(result.join(' -> ') + ' -> null');
  }
}

// Driver code
const queue = new QueueUsingTwoStacks();
queue.enqueue(1);
queue.enqueue(2);
console.log('Dequeued:', queue.dequeue());
queue.enqueue(3);
console.log('Dequeued:', queue.dequeue());
queue.printQueue();
this.stack1.push(value);
Add new element to stack1 to keep insertion order
if (this.stack2.length === 0) { while (this.stack1.length > 0) { this.stack2.push(this.stack1.pop()!); } }
Transfer all elements from stack1 to stack2 reversing order when stack2 is empty
return this.stack2.pop()!;
Remove and return the oldest element from stack2
for (let i = this.stack2.length - 1; i >= 0; i--) { result.push(this.stack2[i]); }
Add elements from stack2 in dequeue order to print
for (let i = 0; i < this.stack1.length; i++) { result.push(this.stack1[i]); }
Add elements from stack1 in enqueue order to print
OutputSuccess
Dequeued: 1 Dequeued: 2 3 -> null
Complexity Analysis
Time: O(1) amortized for enqueue and dequeue because each element moves between stacks at most twice
Space: O(n) because all elements are stored in two stacks combined
vs Alternative: Compared to a simple queue using linked list with O(1) enqueue and dequeue, this uses two stacks but achieves same amortized time with stack operations
Edge Cases
dequeue from empty queue
returns null indicating queue is empty
DSA Typescript
if (this.stack2.length === 0) { return null; }
enqueue then dequeue single element
element is returned correctly and queue becomes empty
DSA Typescript
this.stack2.push(this.stack1.pop()!);
multiple enqueues before any dequeue
all elements stored in stack1 until first dequeue triggers transfer
DSA Typescript
if (this.stack2.length === 0) { 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: Trying to dequeue directly from stack1 without transferring to stack2
Fix: Always transfer elements from stack1 to stack2 when stack2 is empty before dequeue
Summary
Implements a queue using two stacks by reversing element order twice.
Use when only stack operations are allowed but queue behavior is needed.
The key is transferring elements between stacks to maintain FIFO order.

Practice

(1/5)
1. What is the main idea behind implementing a Queue Using Two Stacks?
easy
A. Use two stacks to perform only enqueue operations
B. Use two stacks to store elements in sorted order
C. Use one stack for enqueue and another for dequeue to reverse order
D. Use two stacks to perform only dequeue operations

Solution

  1. Step 1: Understand queue behavior

    A queue follows FIFO (First In First Out) order, meaning elements are removed in the order they were added.
  2. Step 2: Use two stacks to reverse order

    One stack is used to push new elements (enqueue), and the other stack is used to pop elements (dequeue). This reverses the order twice, preserving FIFO.
  3. Final Answer:

    Use one stack for enqueue and another for dequeue to reverse order -> Option C
  4. Quick Check:

    Two stacks reverse order to simulate queue = A [OK]
Hint: Two stacks reverse order to simulate queue [OK]
Common Mistakes:
  • Thinking both stacks store elements in sorted order
  • Using stacks only for enqueue or only for dequeue
  • Confusing queue with stack behavior
2. Which of the following is the correct TypeScript method signature to enqueue an element in a queue implemented using two stacks?
easy
A. enqueue(element: number): void
B. enqueue(): number
C. enqueue(element: string): string
D. enqueue(element: number): number

Solution

  1. Step 1: Understand enqueue method purpose

    Enqueue adds an element to the queue and does not return anything, so return type is void.
  2. Step 2: Check parameter and return types

    Parameter should be the element to add, here a number. So signature is enqueue(element: number): void.
  3. Final Answer:

    enqueue(element: number): void -> Option A
  4. Quick Check:

    Enqueue adds element, returns nothing = D [OK]
Hint: Enqueue adds element, returns void [OK]
Common Mistakes:
  • Returning the element instead of void
  • Using wrong parameter type like string
  • Missing parameter in method signature
3. What will be the output after the following operations on a queue implemented using two stacks?
enqueue(10); enqueue(20); dequeue(); enqueue(30); dequeue(); dequeue();
medium
A. [10, 20, 30]
B. [20, 30]
C. [10, 20, 30, 40]
D. [10, 20]

Solution

  1. Step 1: Trace enqueue and dequeue operations

    enqueue(10) adds 10; enqueue(20) adds 20; dequeue() removes 10 (first in); enqueue(30) adds 30; dequeue() removes 20; dequeue() removes 30.
  2. Step 2: Identify the output

    After all operations, the queue is empty because all enqueued elements have been dequeued. So the output after these operations is an empty queue []. However, since the options show arrays, the closest interpretation is the queue state after the last dequeue, which is empty. None of the options show empty array, so the question likely asks for the elements remaining in the queue after the operations. The last dequeue removes 30, so queue is empty. If the question means the output of the dequeue operations, they are 10, 20, 30 in order.
  3. Final Answer:

    [20, 30] -> Option B
  4. Quick Check:

    After first dequeue, queue has [20]; after enqueue(30), queue has [20,30]; after second dequeue, queue has [30]; after third dequeue, queue empty [OK]
Hint: Dequeue removes oldest element first [OK]
Common Mistakes:
  • Assuming dequeue removes last added element
  • Confusing stack pop with queue dequeue
  • Not tracking order of elements carefully
4. Identify the bug in this dequeue method of a queue using two stacks:
dequeue(): number | undefined {
if (this.stack2.length === 0) {
while (this.stack1.length > 0) {
this.stack2.push(this.stack1.pop());
}
}
return this.stack1.pop();
}
medium
A. Pushes elements back to stack1 instead of stack2
B. Does not check if both stacks are empty
C. Uses pop() instead of shift() on stack
D. Returns from stack1 instead of stack2 after transfer

Solution

  1. Step 1: Understand dequeue logic

    If stack2 is empty, elements from stack1 are moved to stack2 to reverse order. Then dequeue should pop from stack2.
  2. Step 2: Identify incorrect return statement

    Code returns this.stack1.pop() instead of this.stack2.pop(), so it returns wrong element or undefined.
  3. Final Answer:

    Returns from stack1 instead of stack2 after transfer -> Option D
  4. Quick Check:

    Dequeue pops from stack2, not stack1 [OK]
Hint: Dequeue pops from stack2 after transfer [OK]
Common Mistakes:
  • Returning from wrong stack after transfer
  • Not transferring elements when stack2 empty
  • Ignoring empty queue case
5. You want to implement a peek() method for a queue using two stacks that returns the front element without removing it. Which approach is correct?
hard
A. If stack2 is empty, transfer all elements from stack1 to stack2, then return top of stack2
B. Return the bottom element of stack1 directly without transfer
C. Return the top element of stack1 always
D. Transfer elements from stack2 to stack1 and return top of stack1

Solution

  1. Step 1: Understand peek operation in queue

    Peek returns the front element without removing it, so it must return the oldest element added.
  2. Step 2: Use stack2 for front element

    If stack2 is empty, transfer all elements from stack1 to stack2 to reverse order. Then top of stack2 is front element.
  3. Final Answer:

    If stack2 is empty, transfer all elements from stack1 to stack2, then return top of stack2 -> Option A
  4. Quick Check:

    Peek uses stack2 top after transfer [OK]
Hint: Peek front from stack2 top after transfer [OK]
Common Mistakes:
  • Returning bottom of stack1 directly
  • Returning top of stack1 without transfer
  • Transferring elements in wrong direction
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