Implement Stack Using Queue in DSA Typescript - Time & Space Complexity
We want to understand how the time needed changes when we use a queue to build a stack.
Specifically, how fast can we add and remove items when using this method?
Analyze the time complexity of the following code snippet.
class StackUsingQueue {
private queue: number[] = [];
push(x: number): void {
this.queue.push(x);
for (let i = 0; i < this.queue.length - 1; i++) {
this.queue.push(this.queue.shift()!);
}
}
pop(): number | undefined {
return this.queue.shift();
}
}
This code uses one queue to simulate a stack by rotating elements after each push.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop inside the push method that moves elements from front to back.
- How many times: It runs once for each element already in the queue, so roughly n times when pushing the nth element.
Each push moves all existing elements to the back, so the work grows as the stack grows.
| Input Size (n) | Approx. Operations in push |
|---|---|
| 10 | About 9 moves |
| 100 | About 99 moves |
| 1000 | About 999 moves |
Pattern observation: The number of moves grows linearly with the number of elements.
Time Complexity: O(n) for push, O(1) for pop
This means pushing takes longer as the stack grows, but popping is always quick.
[X] Wrong: "Push and pop both take constant time because queues are fast."
[OK] Correct: Because push rotates all elements to keep stack order, it takes time proportional to the number of elements.
Understanding this helps you explain how data structures can be combined and what trade-offs happen in time costs.
What if we used two queues instead of one? How would the time complexity of push and pop change?
Practice
Solution
Step 1: Understand stack and queue operations
A stack follows Last-In-First-Out (LIFO) and a queue follows First-In-First-Out (FIFO).Step 2: Simulate stack using queue(s)
By using one or two queues cleverly, we can reorder elements to behave like a stack.Final Answer:
Use one or two queues to simulate stack operations like push and pop -> Option DQuick Check:
Stack via queue = simulate LIFO with FIFO [OK]
- Confusing stack and queue order
- Thinking queue sorts elements automatically
- Using stack to implement queue instead
Solution
Step 1: Check correct TypeScript array declaration
To declare a queue as an array of numbers, use const queue: number[] = [];Step 2: Identify incorrect declarations
let queue = new Stack<number>(); uses Stack, not queue; C is an empty object; A uses undefined type Queue.Final Answer:
const queue: number[] = []; -> Option AQuick Check:
Array queue declaration = const queue: number[] = [] [OK]
- Using Stack instead of array for queue
- Declaring queue as empty object {}
- Using undefined types without import
class StackUsingQueue {
private queue: number[] = [];
push(x: number) {
this.queue.push(x);
for (let i = 0; i < this.queue.length - 1; i++) {
this.queue.push(this.queue.shift()!);
}
}
pop(): number | undefined {
return this.queue.shift();
}
}
const stack = new StackUsingQueue();
stack.push(1);
stack.push(2);
stack.push(3);
console.log(stack.pop());
console.log(stack.pop());Solution
Step 1: Trace push operations
Push 1: queue=[1]
Push 2: queue=[2,1] after rotation
Push 3: queue=[3,2,1] after rotationStep 2: Trace pop operations
Pop returns queue.shift(): 3, then next pop returns 2.Final Answer:
3 2 -> Option AQuick Check:
Stack pop order = 3 then 2 [OK]
- Not rotating queue after push
- Assuming pop removes last element of array
- Confusing shift() with pop()
class StackUsingTwoQueues {
private q1: number[] = [];
private q2: number[] = [];
push(x: number) {
this.q1.push(x);
}
pop(): number | undefined {
while (this.q1.length > 1) {
this.q2.push(this.q1.shift()!);
}
return this.q1.shift();
}
}Solution
Step 1: Analyze pop method behavior
Pop moves all but last element from q1 to q2, then removes last from q1.Step 2: Identify missing queue swap
After pop, q1 is empty and q2 has elements, but q1 and q2 are not swapped, so next push/pop fail.Final Answer:
pop() does not swap q1 and q2 after popping; add swap after pop -> Option CQuick Check:
Swap queues after pop to maintain correct state [OK]
- Forgetting to swap queues after pop
- Pushing to wrong queue
- Returning wrong queue element
pop() operation returns the last pushed element efficiently?class StackUsingOneQueue {
private queue: number[] = [];
push(x: number) {
this.queue.push(x);
// What should be done here?
}
pop(): number | undefined {
return this.queue.shift();
}
}Solution
Step 1: Understand stack behavior with one queue
To simulate LIFO, after pushing, rotate queue so new element is at front.Step 2: Rotate queue after push
Move all elements except last pushed to back, so pop (shift) removes last pushed.Final Answer:
After push, rotate the queue by moving all elements except the last to the back -> Option BQuick Check:
Rotate queue after push to simulate stack pop [OK]
- Sorting queue instead of rotating
- Reversing queue array (inefficient)
- Not rotating queue after push
Ready to prove it?
Pass the test and this pattern moves unknown
