Bird
Raised Fist0
DSA Typescriptprogramming

Delete a Node from Circular Linked List in DSA Typescript

Choose your learning style10 modes available
Mental Model
A circular linked list loops back to the start, so deleting a node means adjusting pointers without breaking the loop.
Analogy: Imagine a round table with people holding hands in a circle. Removing one person means their neighbors hold hands directly, keeping the circle unbroken.
1 -> 2 -> 3 -> 4 -> (back to 1)
↑head
Dry Run Walkthrough
Input: list: 1 -> 2 -> 3 -> 4 -> (back to 1), delete node with value 3
Goal: Remove node with value 3 and keep the list circular
Step 1: start at head (node 1), look for node with value 3
1 -> 2 -> 3 -> 4 -> (back to 1)
↑curr at 1
Why: We need to find the node to delete
Step 2: move curr to node 2, check next node's value
1 -> 2 -> 3 -> 4 -> (back to 1)
     ↑curr at 2
Why: Check if next node is the one to delete
Step 3: next node is 3, which matches value to delete
1 -> 2 -> 3 -> 4 -> (back to 1)
     ↑curr at 2
Why: Found node before the one to delete to adjust pointers
Step 4: set curr.next to node 4, skipping node 3
1 -> 2 -> 4 -> (back to 1)
     ↑curr at 2
Why: Remove node 3 by skipping it in the circle
Step 5: list remains circular with node 4 pointing back to 1
1 -> 2 -> 4 -> (back to 1)
↑head
Why: Circle is intact after deletion
Result:
1 -> 2 -> 4 -> (back to 1)
Annotated Code
DSA Typescript
class Node {
  value: number;
  next: Node | null;
  constructor(value: number) {
    this.value = value;
    this.next = null;
  }
}

class CircularLinkedList {
  head: Node | null = null;

  insert(value: number) {
    const newNode = new Node(value);
    if (!this.head) {
      newNode.next = newNode;
      this.head = newNode;
      return;
    }
    let curr = this.head;
    while (curr.next !== this.head) {
      curr = curr.next!;
    }
    curr.next = newNode;
    newNode.next = this.head;
  }

  delete(value: number) {
    if (!this.head) return;

    // If head is the only node and matches value
    if (this.head.value === value && this.head.next === this.head) {
      this.head = null;
      return;
    }

    let curr = this.head;
    // If head needs to be deleted
    if (this.head.value === value) {
      // Find last node to update its next pointer
      while (curr.next !== this.head) {
        curr = curr.next!;
      }
      curr.next = this.head.next;
      this.head = this.head.next;
      return;
    }

    // For other nodes
    let prev = this.head;
    curr = this.head.next!;
    while (curr !== this.head) {
      if (curr.value === value) {
        prev.next = curr.next;
        return;
      }
      prev = curr;
      curr = curr.next!;
    }
  }

  print() {
    if (!this.head) {
      console.log('List is empty');
      return;
    }
    let curr = this.head;
    let result = '';
    do {
      result += curr.value + ' -> ';
      curr = curr.next!;
    } while (curr !== this.head);
    result += '(back to ' + this.head.value + ')';
    console.log(result);
  }
}

// Driver code
const cll = new CircularLinkedList();
cll.insert(1);
cll.insert(2);
cll.insert(3);
cll.insert(4);
cll.print();
cll.delete(3);
cll.print();
if (!this.head) return;
handle empty list - nothing to delete
if (this.head.value === value && this.head.next === this.head) { this.head = null; return; }
delete only node if it matches value
if (this.head.value === value) { while (curr.next !== this.head) { curr = curr.next!; } curr.next = this.head.next; this.head = this.head.next; return; }
delete head node by updating last node's next and moving head
while (curr !== this.head) { if (curr.value === value) { prev.next = curr.next; return; } prev = curr; curr = curr.next!; }
traverse to find node to delete and update previous node's next
OutputSuccess
1 -> 2 -> 3 -> 4 -> (back to 1) 1 -> 2 -> 4 -> (back to 1)
Complexity Analysis
Time: O(n) because in worst case we traverse all nodes once to find the node to delete
Space: O(1) because we only use a few pointers and no extra data structures
vs Alternative: Compared to singly linked list deletion, circular list requires careful pointer updates to maintain the loop, but time complexity remains similar
Edge Cases
empty list
delete does nothing, list remains empty
DSA Typescript
if (!this.head) return;
single node list with matching value
list becomes empty after deletion
DSA Typescript
if (this.head.value === value && this.head.next === this.head) {
  this.head = null;
  return;
}
delete head node in multi-node list
head moves to next node, last node's next updated
DSA Typescript
if (this.head.value === value) {
  while (curr.next !== this.head) {
    curr = curr.next!;
  }
  curr.next = this.head.next;
  this.head = this.head.next;
  return;
}
delete node not present
list remains unchanged
DSA Typescript
while (curr !== this.head) {
  if (curr.value === value) {
    prev.next = curr.next;
    return;
  }
  prev = curr;
  curr = curr.next!;
}
When to Use This Pattern
When you see a problem asking to remove an element from a circular linked list, use pointer updates carefully to keep the circle intact without breaking links.
Common Mistakes
Mistake: Not updating the last node's next pointer when deleting the head node
Fix: Find the last node and update its next pointer to the new head before deleting the old head
Mistake: Breaking the circular link by setting next to null accidentally
Fix: Always ensure next pointers point to a node in the list or back to head to maintain circularity
Summary
Deletes a node with a given value from a circular linked list while keeping the list circular.
Use when you need to remove elements from a circular linked list without breaking the loop.
The key is to adjust pointers carefully, especially when deleting the head node, to maintain the circle.

Practice

(1/5)
1. What happens when you delete the only node in a circular linked list?
easy
A. The list becomes empty (null).
B. The list still contains the deleted node.
C. The list points to itself indefinitely.
D. The list throws an error.

Solution

  1. Step 1: Understand the single node case

    When there is only one node, it points to itself forming a circle.
  2. Step 2: Delete the only node

    Removing this node leaves no nodes, so the list becomes empty (null).
  3. Final Answer:

    The list becomes empty (null). -> Option A
  4. Quick Check:

    Single node deleted = empty list [OK]
Hint: Deleting last node empties the list [OK]
Common Mistakes:
  • Assuming list still has nodes after deleting the only node
  • Not setting head to null after deletion
2. Which of the following is the correct way to update the previous node's next pointer when deleting a node in a circular linked list?
easy
A. prev.next = node.next;
B. node.next = prev.next;
C. prev = node.next;
D. node = prev.next;

Solution

  1. Step 1: Identify the pointer to update

    To remove a node, the previous node's next pointer must skip the node to delete.
  2. Step 2: Update the previous node's next pointer

    Set prev.next to node.next to bypass the node being deleted.
  3. Final Answer:

    prev.next = node.next; -> Option A
  4. Quick Check:

    prev.next points to node.next [OK]
Hint: Prev node's next skips deleted node [OK]
Common Mistakes:
  • Assigning node.next to prev.next instead of the other way
  • Changing the node variable instead of prev.next
3. Consider the circular linked list: 10 -> 20 -> 30 -> (back to 10). If we delete the node with value 20, what will be the new list?
medium
A. 10 -> 20 -> 30 -> (back to 10)
B. 10 -> 30 -> (back to 10)
C. 20 -> 30 -> (back to 20)
D. 30 -> 10 -> (back to 30)

Solution

  1. Step 1: Identify node to delete and its previous node

    Node with value 20 is between 10 and 30. Previous node is 10.
  2. Step 2: Update previous node's next pointer

    Set 10's next pointer to 30, skipping 20.
  3. Final Answer:

    10 -> 30 -> (back to 10) -> Option B
  4. Quick Check:

    Deleted 20, list links 10 to 30 [OK]
Hint: Link previous node to next of deleted node [OK]
Common Mistakes:
  • Not updating the previous node's next pointer
  • Deleting wrong node or not updating links
4. Given this TypeScript code snippet to delete a node from a circular linked list, what is the error?
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;
}
medium
A. Does not handle the empty list case.
B. Uses 'do-while' incorrectly causing infinite loop.
C. Returns null even if node is not found.
D. Does not update the tail node's next pointer when deleting head.

Solution

  1. Step 1: Analyze deletion of head node

    If deleting head, code sets head to curr.next but does not update tail's next pointer.
  2. Step 2: Identify missing tail update

    In circular list, tail's next must point to new head to maintain circularity.
  3. Final Answer:

    Does not update the tail node's next pointer when deleting head. -> Option D
  4. Quick Check:

    Tail.next must update on head deletion [OK]
Hint: Update tail's next when head is deleted [OK]
Common Mistakes:
  • Ignoring tail pointer update after head deletion
  • Assuming head change auto-updates tail's next
5. You have a circular linked list with nodes: 5 -> 10 -> 15 -> 20 -> (back to 5). You want to delete the node with value 5 (head node). Which steps correctly delete the head and maintain the circular list?
hard
A. Delete head node and set head to null.
B. Set head to head.next only, no other changes.
C. Find tail node, set tail.next to head.next, update head to head.next.
D. Find tail node, set tail.next to null, update head to head.next.

Solution

  1. Step 1: Find the tail node

    Traverse list to find node whose next points to head (value 20).
  2. 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.
  3. Final Answer:

    Find tail node, set tail.next to head.next, update head to head.next. -> Option C
  4. Quick Check:

    Tail.next points to new head after deletion [OK]
Hint: Update tail.next before changing head [OK]
Common Mistakes:
  • Not updating tail.next causing broken circular link
  • Setting tail.next to null breaks circular list
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard