CMD Guide
HomeDSALinked List

Introduction to LinkedList

A linked list stores a sequence of values by giving each element a pointer to the next one, so the collection can grow or shrink by rewiring a couple of pointers rather than moving any existing data — the trade-off it makes for that flexibility is giving up direct index-based access, since the only way to reach the k-th node is to walk the chain from the head.

Anatomy

Recognize the pattern

Reach for a linked list — or recognize one is in play — when you see: frequent insert/delete at the front or a known middle position without shifting elements; an unbounded/unknown final size; a need to splice two sequences together cheaply; or when the problem explicitly gives you ListNode/next and asks for reversal, cycle detection, merging, or k-th-from-end — these are the classic tells that array-index tricks won't apply and pointer manipulation is the intended tool.

Brute force vs. optimal, on the operations that matter

OperationArrayLinked List
Insert at frontO(n) — shift all elements rightO(1) — 2 pointer touches: newNode.next = head; head = newNode
Delete at frontO(n) — shift all elements leftO(1) — 1 pointer touch: head = head.next
Insert/delete at known nodeO(n) shiftO(1) relink (if you already hold the predecessor)
Access element iO(1) — pointer arithmeticO(n) — must walk from head
Search valueO(n)O(n)

The array's weakness (shifting on insert/delete) is exactly the linked list's strength, and vice versa for access. There is no free win — you're trading random access for O(1) structural edits.

Complexity, derived

Time. Insertion/deletion at a node you already hold a reference to touches a constant number of pointer fields (1–3 reassignments depending on the operation, see table above) regardless of list length → O(1). Finding that node in the first place requires following next pointers one at a time starting at head; in the worst case (target at the tail, or absent) that's n dereferences → O(n). So "linked-list insert is O(1)" is only true for the splice itself, not including the search to locate the splice point.

Space. Per-node overhead is JVM/heap-config dependent, not a fixed number: on HotSpot with the default Compressed Oops (enabled automatically for heaps under ~32GB), an object reference is 4 bytes, not 8 — 8-byte references only apply once compressed oops is disabled or the heap exceeds that threshold. On top of the pointer field, every node also carries an object header (typically 12–16 bytes on HotSpot for mark word + class pointer), which usually outweighs the pointer field itself in real accounting. So total space is O(n) for payload data plus O(n) per-node overhead (header + one reference), versus an array's O(n) with no per-element pointer or header cost but potential unused pre-allocated capacity.

Traced example — building 10 → 20 → 30 and inserting 15

  1. Start: head = null.
  2. insertEnd(10): new node A(10,null); head = A. List: 10.
  3. insertEnd(20): new node B(20,null); A.next = B. List: 10 → 20.
  4. insertEnd(30): new node C(30,null); B.next = C. List: 10 → 20 → 30.
  5. Insert 15 after value 20: walk head→A(10)→B(20), found B. Create new node D(15, null). Splice in pointer-safe order: first D.next = B.next (so D now points to C, preserving the rest of the chain), then B.next = D (so B now points to D). List: 10 → 20 → 15 → 30.

Steps 2–4 and the splice in step 5 are each O(1) pointer work; the walk in step 5 to find B costs O(n). The order in step 5 matters: setting D.next before overwriting B.next is what prevents the tail (C) from being orphaned — doing it in reverse would lose the rest of the list.

Reference implementation

class Node {
    int data;
    Node next;
    Node(int data) { this.data = data; this.next = null; }
}

class LinkedList {
    Node head;

    void insertEnd(int value) {
        Node n = new Node(value);
        if (head == null) { head = n; return; }
        Node cur = head;
        while (cur.next != null) cur = cur.next; // O(n) walk (no cached tail)
        cur.next = n;                             // O(1) splice
    }

    void insertAfterValue(int target, int value) {
        Node cur = head;
        while (cur != null && cur.data != target) cur = cur.next; // O(n)
        if (cur == null) return; // target not found
        Node n = new Node(value);
        n.next = cur.next;       // capture the rest of the chain first
        cur.next = n;            // O(1) splice
    }
}

Pitfalls

When to use / when not

Use a linked list when insert/delete at the ends or at an already-located position dominates and list size is unpredictable (e.g., LRU cache eviction list, adjacency lists, undo stacks). Avoid it when you need random access by index, binary search, or cache-friendly iteration — an array / ArrayList wins there, trading O(n) worst-case resize for O(1) amortized append and O(1) index access. A dynamic array is almost always the better default in modern managed languages unless structural churn in the middle of the sequence is frequent and locatable in O(1).

The five transferable moves

Nearly every interview list problem is a combination of a few reusable moves, not a new algorithm each time:

Takeaways

Recall: Why is inserting a new node after a known node O(1), but inserting "the value after 20" overall still O(n)?


Synthesized from the source lesson plus standard CS data-structures references (CLRS-style linked list analysis) and HotSpot JVM object layout documentation.

🤖 Don't fully get this? Learn it with Claude

Stuck on Introduction to LinkedList? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Introduction to LinkedList** (DSA) and want to truly understand it. Explain Introduction to LinkedList from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Introduction to LinkedList** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Introduction to LinkedList** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Introduction to LinkedList** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes