Delete from End of Doubly Linked List in DSA Typescript - Time & Space Complexity
We want to know how long it takes to remove the last item from a doubly linked list.
How does the time needed change as the list gets bigger?
Analyze the time complexity of the following code snippet.
class Node {
value: number;
next: Node | null;
prev: Node | null;
constructor(value: number) {
this.value = value;
this.next = null;
this.prev = null;
}
}
function deleteFromEnd(head: Node | null): Node | null {
if (!head) return null;
let current = head;
while (current.next) {
current = current.next;
}
if (current.prev) {
current.prev.next = null;
} else {
head = null;
}
return head;
}
This code removes the last node from a doubly linked list by walking to the end and unlinking it.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through each node to find the last one.
- How many times: It runs once for each node until the last, so as many times as the list length minus one.
As the list gets longer, the time to reach the last node grows directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps to reach the end |
| 100 | About 100 steps to reach the end |
| 1000 | About 1000 steps to reach the end |
Pattern observation: The steps grow in a straight line with the list size.
Time Complexity: O(n)
This means the time to delete the last node grows directly with the number of nodes in the list.
[X] Wrong: "Deleting the last node is always quick and takes the same time no matter the list size."
[OK] Correct: Because we must walk through the list to find the last node, the time depends on how long the list is.
Understanding this helps you explain how linked lists work and how operations depend on list size, a key skill in many coding interviews.
"What if we kept a pointer to the tail node? How would the time complexity change when deleting from the end?"
Practice
tail pointer when you delete the last node from a doubly linked list?Solution
Step 1: Understand the tail pointer role
The tail pointer always points to the last node in the list.Step 2: Effect of deleting the last node
When the last node is deleted, the tail must move to the previous node to remain the last node.Final Answer:
It moves to the previous node of the deleted node -> Option BQuick Check:
Tail updates to previous node after deletion [OK]
- Setting tail to null without checking if list is empty
- Not updating tail pointer after deletion
- Confusing head and tail pointers
- Assuming tail points to head after deletion
tail is not null?Solution
Step 1: Move tail pointer to previous node
To delete the last node, tail must point to its previous node:tail = tail.prev;Step 2: Set new tail's next to null
Since tail is now last node, itsnextmust benull:tail.next = null;Final Answer:
tail = tail.prev; tail.next = null; -> Option AQuick Check:
Correct syntax moves tail back and nullifies next [OK]
- Moving tail forward instead of backward
- Not setting tail.next to null
- Setting tail to null without updating links
- Confusing prev and next pointers
Solution
Step 1: Identify the last node
The last node is 4, pointed by tail.Step 2: Delete last node and update tail
Remove node 4, update tail to node 3, set tail.next to null.Final Answer:
1 <-> 2 <-> 3 <-> null -> Option AQuick Check:
Last node 4 removed, tail now 3 [OK]
- Not updating tail pointer
- Leaving deleted node linked
- Removing wrong node
- Confusing head and tail updates
if (tail !== null) {
tail = tail.prev;
tail.next = null;
}
What error can occur here?Solution
Step 1: Analyze single-node list case
If list has one node, tail.prev is null, so tail becomes null.Step 2: Accessing tail.next causes error
After tail = tail.prev (null), next line tries tail.next = null, causing runtime error (cannot access property of null).Final Answer:
Runtime error if list has only one node -> Option CQuick Check:
Null tail causes runtime error on next access [OK]
- Not handling single-node list edge case
- Assuming tail is never null after update
- Ignoring runtime null pointer errors
- Confusing syntax errors with runtime errors
Solution
Step 1: Delete last node first time
Last node 30 is removed, tail moves to 20, list becomes 10 <-> 20 <-> null.Step 2: Delete last node second time
Last node 20 is removed, tail moves to 10, list becomes 10 <-> null.Step 3: Verify final list
After two deletions, list is 10 <-> null.Final Answer:
10 <-> null -> Option DQuick Check:
Two deletions remove 30 and 20, leaving 10 [OK]
- Deleting only one node instead of two
- Confusing node values after deletion
- Not updating tail pointer correctly
- Assuming list becomes empty too early
Ready to prove it?
Pass the test and this pattern moves unknown
