Attic
DSALinked Lists

Core Operations

Insertion, deletion, traversal, and edge-case handling using sentinel dummy heads

Every linked list operation boils down to modifying reference pointers without losing references to the rest of the chain. This guide covers fundamental pointer mechanics and the industry-standard sentinel pattern.


The Sentinel (Dummy Head) Pattern

In linked list algorithms, modifying the first node (head) typically requires cumbersome if (head == null) or if (target == head) edge-case branches.

The Sentinel (Dummy Head) technique creates an artificial placeholder node positioned directly before the actual head:

SentinelPattern.java
ListNode dummy = new ListNode(-1);
dummy.next = head;

// Any manipulation (inserting at head, deleting head) is now identical
// to manipulating any normal internal node!

// Return the true head at the conclusion:
return dummy.next;

Why Dummy Heads Are Mandatory in Interviews: It guarantees that the node to be inserted or removed always has a non-null predecessor (prev), eliminating null-pointer exceptions and messy special cases.


1. Insertion Operations

InsertAtHead.java
public ListNode insertAtHead(ListNode head, int val) {
    ListNode newNode = new ListNode(val);
    newNode.next = head;
    return newNode; // New node is now the head
}

Time Complexity: O(1) instantaneous pointer assignment.


2. Deletion Operations

To delete a target node, locate the node immediately preceding it (prev), and bypass the target by linking prev.next = target.next.

Delete by Value

DeleteByValue.java
public ListNode removeElements(ListNode head, int targetVal) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode curr = dummy;

    while (curr.next != null) {
        if (curr.next.val == targetVal) {
            curr.next = curr.next.next; // Bypass matching node
        } else {
            curr = curr.next;
        }
    }

    return dummy.next;
}

3. Delete Node Without Access to Head (Interview Trick)

Suppose you are given access only to the node that needs to be deleted, with no reference to the head pointer:

DeleteNodeInPlace.java
public void deleteNode(ListNode node) {
    // Copy the value of the next node into current node
    node.val = node.next.val;

    // Bypass the next node
    node.next = node.next.next;
}

Limitation: This trick cannot be used if the node to delete is the very last tail node of the list (since node.next == null).


4. Doubly Linked List Pointer Mechanics

In a DoublyListNode, every node maintains both prev and next pointers. This allows O(1) instant deletion of any node without needing to traverse to find its predecessor:

DoublyLinkedListOperations.java
// Delete a given node in O(1) time
public void removeNode(DoublyListNode node) {
    DoublyListNode prevNode = node.prev;
    DoublyListNode nextNode = node.next;

    if (prevNode != null) {
        prevNode.next = nextNode;
    }
    if (nextNode != null) {
        nextNode.prev = prevNode;
    }

    // Detach node references for garbage collection
    node.prev = null;
    node.next = null;
}

// Insert newNode immediately after targetNode in O(1) time
public void insertAfter(DoublyListNode targetNode, DoublyListNode newNode) {
    newNode.next = targetNode.next;
    newNode.prev = targetNode;

    if (targetNode.next != null) {
        targetNode.next.prev = newNode;
    }
    targetNode.next = newNode;
}

Complexity Profile of Core Operations

OperationSingly Linked ListSingly List (with Tail)Doubly Linked ListArray (ArrayList)
Insert at HeadO(1)O(1)O(1)O(n)
Insert at TailO(n)O(1)O(1)O(1) amortized
Delete HeadO(1)O(1)O(1)O(n)
Delete TailO(n) (must find second-to-last)O(n)O(1) (with tail)O(1)
Delete Given NodeO(n)O(n)O(1) (direct pointer)O(n)
Search by ValueO(n)O(n)O(n)O(n) (or O(log n) sorted)
Get by IndexO(n)O(n)O(n)O(1)

On this page