Insert at Specific Position in Doubly Linked List in DSA Typescript - Time & Space Complexity
We want to know how the time to insert a node at a certain position in a doubly linked list changes as the list grows.
How does the number of steps grow when the list gets longer?
Analyze the time complexity of the following code snippet.
function insertAtPosition(head: Node | null, data: number, position: number): Node | null {
if (position === 1) {
const newNode = new Node(data);
newNode.next = head;
if (head) head.prev = newNode;
return newNode;
}
let current = head;
let count = 1;
while (current && count < position - 1) {
current = current.next;
count++;
}
if (!current) return head;
const newNode = new Node(data);
newNode.next = current.next;
if (current.next) current.next.prev = newNode;
current.next = newNode;
newNode.prev = current;
return head;
}
This code inserts a new node at a given position in a doubly linked list by moving through the list to find the right spot.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through the list nodes to reach the position before insertion.
- How many times: Up to position - 2 times, which depends on the input position.
As the list gets longer, the steps to reach the insertion point grow roughly in direct proportion to the position number.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 9 steps to reach position |
| 100 | Up to 99 steps to reach position |
| 1000 | Up to 999 steps to reach position |
Pattern observation: The number of steps grows linearly with the position where we insert.
Time Complexity: O(n)
This means the time to insert grows in a straight line with the size of the list or the position where we insert.
[X] Wrong: "Inserting at any position in a doubly linked list always takes constant time because we can go backwards and forwards."
[OK] Correct: We still need to move through the list to find the position, which takes time proportional to the position number, so it is not constant time.
Understanding how insertion time depends on position helps you explain and reason about linked list operations clearly, a skill valued in many coding discussions.
"What if we kept a pointer to the tail and inserted near the end? How would the time complexity change?"
Practice
Solution
Step 1: Understand doubly linked list structure
Each node has pointers to both previous and next nodes, so insertion requires updating these pointers.Step 2: Insert node at specific position
We must update the previous node's next pointer and the next node's previous pointer to point to the new node.Final Answer:
Adjusting the previous and next pointers of neighboring nodes to include the new node -> Option AQuick Check:
Pointer updates = Adjust neighbors [OK]
- Only updating one pointer leads to broken links
- Ignoring the previous pointer in insertion
- Replacing nodes instead of inserting
Solution
Step 1: Check for previous and next pointers
A doubly linked list node must have both next and prev pointers, which can be null.Step 2: Verify constructor initializes all properties
class Node { value: number; next: Node | null; prev: Node | null; constructor(value: number) { this.value = value; this.next = null; this.prev = null; } } initializes value, next, and prev correctly with proper types.Final Answer:
class Node { value: number; next: Node | null; prev: Node | null; constructor(value: number) { this.value = value; this.next = null; this.prev = null; } } -> Option DQuick Check:
Both pointers initialized = class Node { value: number; next: Node | null; prev: Node | null; constructor(value: number) { this.value = value; this.next = null; this.prev = null; } } [OK]
- Forgetting to initialize prev pointer
- Using wrong property names
- Not allowing null for next or prev
insertAtPosition(head, 3, 3);Positions start at 1.
Solution
Step 1: Identify position 3 in the list
Positions: 1=1, 2=2, 3=4. We want to insert before node with value 4.Step 2: Insert node with value 3 at position 3
Update pointers so 2 points next to 3, 3 points prev to 2 and next to 4, 4 points prev to 3.Final Answer:
1 <-> 2 <-> 3 <-> 4 -> Option AQuick Check:
Insert at position 3 = 1-2-3-4 [OK]
- Inserting after instead of before position
- Mixing up prev and next pointers
- Off-by-one errors in position counting
function insertAtPosition(head: Node | null, value: number, position: number): Node | null {
let newNode = new Node(value);
if (position === 1) {
newNode.next = head;
if (head) head.prev = newNode;
return newNode;
}
let current = head;
for (let i = 1; i < position - 1; i++) {
if (!current) return head;
current = current.next;
}
newNode.next = current.next;
current.next = newNode;
newNode.prev = current;
return head;
}Solution
Step 1: Analyze pointer updates after insertion
After inserting newNode, newNode.next.prev should point back to newNode to maintain doubly links.Step 2: Identify missing pointer update
The code misses updating newNode.next.prev = newNode, which breaks backward link from next node.Final Answer:
Missing update of newNode.next.prev to newNode -> Option CQuick Check:
Update both next and prev pointers [OK]
- Forgetting to update newNode.next.prev
- Loop off-by-one errors
- Not handling empty list insertion
Solution
Step 1: Identify position 2 in the list
Positions: 1=Engine, 2=Car1. Insert CarX before Car1 to become new position 2.Step 2: Insert CarX at position 2
Update pointers so Engine next points to CarX, CarX prev to Engine, CarX next to Car1, Car1 prev to CarX.Final Answer:
Engine <-> CarX <-> Car1 <-> Car2 <-> Caboose -> Option BQuick Check:
Insert at position 2 = Engine-CarX-Car1... [OK]
- Inserting after instead of before position
- Not updating prev pointers correctly
- Confusing position indexing starting at 0
Ready to prove it?
Pass the test and this pattern moves unknown
