Insert at Beginning of Doubly Linked List in DSA Typescript - Time & Space Complexity
We want to know how the time to add a new node at the start of a doubly linked list changes as the list grows.
How does the number of steps grow when the list gets bigger?
Analyze the time complexity of the following code snippet.
class Node {
data: number;
prev: Node | null = null;
next: Node | null = null;
constructor(data: number) { this.data = data; }
}
function insertAtBeginning(head: Node | null, data: number): Node {
const newNode = new Node(data);
newNode.next = head;
if (head !== null) head.prev = newNode;
return newNode;
}
This code creates a new node and inserts it at the start of the doubly linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Creating and linking a single new node.
- How many times: Only once per insertion, no loops or recursion involved.
Adding a node at the start always takes the same steps, no matter how big the list is.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 4-5 steps |
| 100 | 4-5 steps |
| 1000 | 4-5 steps |
Pattern observation: The number of steps stays the same regardless of list size.
Time Complexity: O(1)
This means inserting at the beginning takes a constant amount of time no matter how large the list is.
[X] Wrong: "Inserting at the start takes longer as the list grows because we have to move all nodes."
[OK] Correct: We only change a few pointers at the start; no need to move or visit other nodes.
Knowing that insertion at the start is quick helps you explain efficient list operations clearly and confidently.
"What if we changed this to insert at the end of the doubly linked list without a tail pointer? How would the time complexity change?"
Practice
Solution
Step 1: Understand the head node position
The head node is the first node in the doubly linked list.Step 2: Insert new node before head
Inserting at the beginning means placing the new node before the current head, making it the new head.Final Answer:
To add a new node before the current head node -> Option DQuick Check:
Insert at beginning = add before head [OK]
- Confusing insertion at beginning with insertion at end
- Thinking insertion deletes nodes
- Mixing up head and tail nodes
Solution
Step 1: Set newNode.next to current head
The new node's next pointer should point to the current head node.Step 2: Update current head's prev to newNode if head exists
If the list is not empty, the current head's prev pointer must point back to the new node.Step 3: Update head to newNode
Finally, the head pointer is updated to the new node.Final Answer:
newNode.next = head; if(head) head.prev = newNode; head = newNode; -> Option AQuick Check:
Set newNode.next=head, head.prev=newNode, head=newNode [OK]
- Swapping next and prev pointers
- Not updating head pointer
- Setting newNode.prev incorrectly
class Node {
data: number;
next: Node | null = null;
prev: Node | null = null;
constructor(data: number) { this.data = data; }
}
let head: Node | null = new Node(10);
head.next = new Node(20);
head.next.prev = head;
const newNode = new Node(5);
newNode.next = head;
head.prev = newNode;
head = newNode;
// Print list
let temp = head;
const result: number[] = [];
while(temp) {
result.push(temp.data);
temp = temp.next;
}
console.log(result);Solution
Step 1: Initial list before insertion
List is 10 <-> 20, head points to 10.Step 2: Insert newNode with data 5 at beginning
newNode.next = head (10), head.prev = newNode, head = newNode (5).Step 3: Traverse list from new head
Traverse from 5: 5 -> 10 -> 20.Final Answer:
[5, 10, 20] -> Option AQuick Check:
New head 5 followed by 10 and 20 [OK]
- Not updating head to newNode
- Incorrectly linking prev pointers
- Printing list from old head
const newNode = new Node(15); newNode.prev = null; newNode.next = head; head.prev = newNode; head = newNode;
Solution
Step 1: Check if head is null before accessing head.prev
If the list is empty (head is null), accessing head.prev causes an error.Step 2: Add condition to update head.prev only if head exists
Use if(head) head.prev = newNode; to avoid runtime error.Final Answer:
Missing check if head is null before accessing head.prev -> Option BQuick Check:
Always check head before head.prev [OK]
- Ignoring null head and causing runtime error
- Swapping next and prev pointers
- Assigning head too early
Solution
Step 1: Insert new node with value 20 before current head 30
New node becomes head, its prev is null, next points to old head (30).Step 2: Update old head's prev to new node
Old head (30) prev pointer updated to new node (20).Step 3: Confirm list order and pointers
List order is 20 <-> 30 <-> 40 <-> 50 with new head prev=null, next=30.Final Answer:
List: 20 <-> 30 <-> 40 <-> 50; new head prev = null, next points to 30 -> Option CQuick Check:
New head prev=null, next=old head [OK]
- Setting new head prev to old tail
- Reversing list order accidentally
- Not updating old head prev pointer
Ready to prove it?
Pass the test and this pattern moves unknown
