Delete a Node from Circular Linked List in DSA Typescript - Time & Space Complexity
When deleting a node from a circular linked list, we want to know how the time to find and remove the node changes as the list grows.
We ask: How many steps does it take to delete a node depending on the list size?
Analyze the time complexity of the following code snippet.
function deleteNode(head: Node | null, key: number): Node | null {
if (!head) return null;
let curr = head, prev = null;
do {
if (curr.data === key) {
if (prev) prev.next = curr.next;
else {
// find last node to update its next
let last = head;
while (last.next !== head) last = last.next;
if (last === head) {
return null;
}
last.next = curr.next;
head = curr.next;
}
break;
}
prev = curr;
curr = curr.next;
} while (curr !== head);
return head;
}
This code searches for a node with a given value and removes it from the circular linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop that traverses nodes to find the target node.
- How many times: Up to n times, where n is the number of nodes in the list.
As the list grows, the search loop may need to check more nodes before finding the target.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 10 checks |
| 100 | Up to 100 checks |
| 1000 | Up to 1000 checks |
Pattern observation: The number of steps grows roughly in direct proportion to the list size.
Time Complexity: O(n)
This means the time to delete a node grows linearly with the number of nodes in the list.
[X] Wrong: "Deleting a node in a circular linked list always takes constant time because we just change pointers."
[OK] Correct: We must first find the node to delete, which can take time proportional to the list size.
Understanding this helps you explain how linked list operations scale and shows you can reason about pointer-based data structures clearly.
"What if the list had a direct pointer to the node to delete? How would the time complexity change?"
Practice
Solution
Step 1: Understand the single node case
When there is only one node, it points to itself forming a circle.Step 2: Delete the only node
Removing this node leaves no nodes, so the list becomes empty (null).Final Answer:
The list becomes empty (null). -> Option AQuick Check:
Single node deleted = empty list [OK]
- Assuming list still has nodes after deleting the only node
- Not setting head to null after deletion
Solution
Step 1: Identify the pointer to update
To remove a node, the previous node's next pointer must skip the node to delete.Step 2: Update the previous node's next pointer
Set prev.next to node.next to bypass the node being deleted.Final Answer:
prev.next = node.next; -> Option AQuick Check:
prev.next points to node.next [OK]
- Assigning node.next to prev.next instead of the other way
- Changing the node variable instead of prev.next
Solution
Step 1: Identify node to delete and its previous node
Node with value 20 is between 10 and 30. Previous node is 10.Step 2: Update previous node's next pointer
Set 10's next pointer to 30, skipping 20.Final Answer:
10 -> 30 -> (back to 10) -> Option BQuick Check:
Deleted 20, list links 10 to 30 [OK]
- Not updating the previous node's next pointer
- Deleting wrong node or not updating links
function deleteNode(head: Node | null, key: number): Node | null {
if (!head) return null;
let curr = head, prev = null;
do {
if (curr.data === key) {
if (prev) prev.next = curr.next;
else head = curr.next;
return head;
}
prev = curr;
curr = curr.next;
} while (curr !== head);
return head;
}Solution
Step 1: Analyze deletion of head node
If deleting head, code sets head to curr.next but does not update tail's next pointer.Step 2: Identify missing tail update
In circular list, tail's next must point to new head to maintain circularity.Final Answer:
Does not update the tail node's next pointer when deleting head. -> Option DQuick Check:
Tail.next must update on head deletion [OK]
- Ignoring tail pointer update after head deletion
- Assuming head change auto-updates tail's next
Solution
Step 1: Find the tail node
Traverse list to find node whose next points to head (value 20).Step 2: Update tail's next pointer and head
Set tail.next to head.next (node with value 10), then update head to head.next.Final Answer:
Find tail node, set tail.next to head.next, update head to head.next. -> Option CQuick Check:
Tail.next points to new head after deletion [OK]
- Not updating tail.next causing broken circular link
- Setting tail.next to null breaks circular list
Ready to prove it?
Pass the test and this pattern moves unknown
