Dequeue Using Linked List in DSA Typescript - Time & Space Complexity
We want to understand how fast operations on a dequeue using a linked list run as the number of items grows.
Specifically, how the time to add or remove items changes when the dequeue gets bigger.
Analyze the time complexity of the following code snippet.
class Node {
value: number;
next: Node | null = null;
prev: Node | null = null;
constructor(value: number) { this.value = value; }
}
class Dequeue {
head: Node | null = null;
tail: Node | null = null;
addFront(value: number) {
const newNode = new Node(value);
if (!this.head) {
this.head = this.tail = newNode;
} else {
newNode.next = this.head;
this.head.prev = newNode;
this.head = newNode;
}
}
}
This code adds an item to the front of a dequeue implemented with a linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Adding a node at the front involves changing a few pointers.
- How many times: Each addFront call does a fixed number of steps, no loops.
Adding one item always takes the same small number of steps, no matter how many items are already in the dequeue.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5-6 steps |
| 100 | 5-6 steps |
| 1000 | 5-6 steps |
Pattern observation: The time stays about the same no matter how big the dequeue grows.
Time Complexity: O(1)
This means adding or removing from the front happens in constant time, quickly and independently of size.
[X] Wrong: "Adding to the front takes longer as the dequeue grows because we have more items."
[OK] Correct: The linked list keeps track of the front, so adding just changes a few pointers, no matter how many items are inside.
Knowing that linked list dequeue operations run in constant time shows you understand efficient data structures, a key skill in coding interviews.
"What if we changed the linked list to a simple array? How would the time complexity of adding to the front change?"
Practice
Solution
Step 1: Understand dequeue operations
A dequeue supports insertion and deletion from both front and rear ends.Step 2: Compare linked list and array
Linked lists allow adding/removing nodes at both ends in constant time, unlike arrays which may require shifting elements.Final Answer:
It allows insertion and deletion from both ends in constant time. -> Option AQuick Check:
Linked list dequeue = O(1) insert/delete both ends [OK]
- Thinking arrays allow constant time insert/delete at front
- Confusing memory usage advantage
- Assuming automatic sorting
Solution
Step 1: Identify method purpose and parameter
Inserting at front requires a method that takes a value (number) and returns nothing (void).Step 2: Match signature with correct naming and types
insertFront(value: number): void matches: method name 'insertFront', parameter 'value: number', return type 'void'. Others have wrong names, return types, or parameter types.Final Answer:
insertFront(value: number): void -> Option AQuick Check:
Insert front method = insertFront(value: number): void [OK]
- Using wrong method names like pushFront
- Wrong return types like number or string
- Incorrect parameter types
const dq = new Dequeue(); dq.insertRear(10); dq.insertFront(20); dq.insertRear(30); dq.deleteFront(); dq.insertFront(40); dq.deleteRear(); dq.display();What will be the printed output?
Solution
Step 1: Trace each operation on dequeue
Start empty. insertRear(10): 10 insertFront(20): 20 -> 10 insertRear(30): 20 -> 10 -> 30 deleteFront(): removes 20, now 10 -> 30 insertFront(40): 40 -> 10 -> 30 deleteRear(): removes 30, now 40 -> 10Step 2: Display final dequeue state
Prints elements from front to rear: 40 -> 10 -> nullFinal Answer:
40 -> 10 -> null -> Option BQuick Check:
After operations, dequeue = 40 -> 10 -> null [OK]
- Forgetting deleteFront removes front element
- Mixing order of insertFront and insertRear
- Not updating links after deleteRear
deleteRear(): number | null {
if (!this.rear) return null;
let temp = this.front;
while (temp.next !== this.rear) {
temp = temp.next;
}
const value = this.rear.value;
this.rear = temp;
this.rear.next = null;
return value;
}Solution
Step 1: Analyze loop and pointers
The loop finds the node before rear by checking temp.next !== rear. If only one node exists, temp.next is null, so loop condition fails immediately.Step 2: Check single node case
If only one node, front and rear point to same node. The code does not update front or rear to null, causing incorrect state after deletion.Final Answer:
It does not handle the case when there is only one node. -> Option DQuick Check:
Single node deleteRear needs special handling [OK]
- Ignoring single-node list case
- Assuming front pointer updates automatically
- Overlooking null pointer exceptions
Solution
Step 1: Understand doubly linked list structure
Each node has pointers to next and previous nodes, allowing backward traversal.Step 2: Use rear pointer and previous link
With rear pointer and previous link, deleting rear node is direct and takes constant time without traversal.Final Answer:
Maintain a rear pointer and use the previous pointer to delete rear in O(1) time. -> Option CQuick Check:
Doubly linked list rear delete = O(1) using prev pointer [OK]
- Traversing from front wastes time
- Using array shifts is inefficient
- Ignoring doubly linked list advantages
Ready to prove it?
Pass the test and this pattern moves unknown
