Linked List Mental Model
Understand node references, non-contiguous storage, head pointers, traversal, insertion, deletion, and why linked lists are rarely a default production choice.
What you will be able to do
A linked list is not a slower array. It is a different storage model: each node owns a value and a reference to the next node. That makes insertion and deletion cheap only when you already have the right node reference. Finding that reference still requires traversal.
The Node Reference Model
Arrays give indexed access. Linked lists give reference-based movement. A list starts at a head node. From there, you can only move through next references until the list ends. This is why random access is O(n), not O(1).
SkillSkore principle
A linked list helps when you already have node references and need cheap local rewiring. It does not help when you repeatedly search by index or value.
Scenario: LRU Cache Order
An LRU cache must move accessed items to the front and evict the least recently used item from the back. A hash map finds the node by key. A doubly linked list rewires that node in O(1). The linked list alone is not enough; the map supplies the missing lookup.
| Need | Structure | Reason |
|---|---|---|
| Find cache entry by key | Hash map | Linked list lookup alone is O(n). |
| Move entry to front | Doubly linked list | Known node can be detached and reinserted. |
| Evict oldest entry | Tail pointer | Oldest node is directly available. |
| Keep correctness | Careful pointer updates | One missed reference corrupts the structure. |
Same Pattern in Java, Python, and JavaScript
Traversal is the first skill. You start at head, visit current, then move to current.next until the pointer is null.
class ListNode {
int value;
ListNode next;
ListNode(int value) { this.value = value; }
}
class LinkedListTraversal {
static int sum(ListNode head) {
int total = 0;
for (ListNode current = head; current != null; current = current.next) {
total += current.value;
}
return total;
}
}Insertion and Deletion Are Local Only After Lookup
The phrase insertion is O(1) is incomplete. Inserting after a known node is O(1). Finding that node by position or value is O(n). Assessment-grade answers always separate lookup cost from rewiring cost.
Assessment trap
Do not say linked lists are better for insertion without stating whether the insertion position is already known.
Interview signalFrequently Asked Interview Questions
These are canonical interview patterns for this topic, phrased as concrete problem statements. They avoid vague theory questions and prepare you for the exact reasoning interviewers expect: invariant, edge cases, complexity, and trade-off.
- Merge two sorted linked lists into one sorted linked list.
- Delete the first node whose value equals target.
- Describe the data structures needed for an LRU cache.
Production practiceCompany-Style Practice Examples
These are not claimed as exact company-specific questions. They are the interview patterns repeatedly used by product companies to test whether you can move from brute force to a defensible implementation.
| Example | Brute-force approach | Stronger solution | Production notes |
|---|---|---|---|
| Merge sorted lists | Copy all values into an array and sort. | Walk both lists and rewire the smaller node each time. | Linear time with pointer discipline. |
| LRU cache shape | Scan a list to find keys. | Use map lookup plus doubly linked recency order. | Hybrid structure covers both lookup and movement. |
| Insert after node | Restart from head for every insertion. | Use the known node reference and rewire locally. | Only O(1) after the node is known. |
Solved modelInterview Question Solutions
Question 1: Merge Two Sorted Lists
Merge two sorted linked lists into one sorted linked list. Use a dummy node and tail pointer. Rewire the smaller current node, advance that list, then append the remainder.
class ListNode { int value; ListNode next; ListNode(int v) { value = v; } }
class MergeSortedLists {
static ListNode merge(ListNode a, ListNode b) {
ListNode dummy = new ListNode(0);
ListNode tail = dummy;
while (a != null && b != null) {
if (a.value <= b.value) { tail.next = a; a = a.next; }
else { tail.next = b; b = b.next; }
tail = tail.next;
}
tail.next = a != null ? a : b;
return dummy.next;
}
}Question 2: Delete Node by Value
Delete the first node whose value equals target. Use a dummy node before head so deleting the original head is not a special case.
class ListNode { int value; ListNode next; ListNode(int v) { value = v; } }
class DeleteValue { static ListNode delete(ListNode head, int target) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode prev = dummy; while (prev.next != null) { if (prev.next.value == target) { prev.next = prev.next.next; break; } prev = prev.next; } return dummy.next; } }Question 3: LRU Cache Structure
Describe the data structures needed for an LRU cache. Use a map for key lookup and a doubly linked list for recency order; map entries point to list nodes.
import java.util.*;
class LruCache<K, V> {
static class Node<K, V> { K key; V value; Node<K, V> prev, next; }
private final Map<K, Node<K, V>> byKey = new HashMap<>();
private Node<K, V> head, tail;
// get: find byKey.get(key), detach node, move to head.
// put: update existing or add new head; if over capacity, remove tail.
}Solved modelWorked Interview Answer
Merge two sorted linked lists into one sorted list. Use a dummy node and a tail pointer. Reuse the smaller current node from either list, then append the remainder.
class ListNode { int value; ListNode next; ListNode(int v) { value = v; } }
class MergeSortedLists {
static ListNode merge(ListNode a, ListNode b) {
ListNode dummy = new ListNode(0);
ListNode tail = dummy;
while (a != null && b != null) {
if (a.value <= b.value) { tail.next = a; a = a.next; }
else { tail.next = b; b = b.next; }
tail = tail.next;
}
tail.next = a != null ? a : b;
return dummy.next;
}
}Hands-on drillTry It Yourself
Practice task
Draw a three-node list A -> B -> C. Insert X after A, then delete B. Write the exact reference updates in order.
Failure patternsCommon Mistakes to Avoid
- Saying insertion is O(1) without including lookup cost.
- Losing the rest of the list by overwriting next too early.
- Forgetting that head can change.
- Ignoring ownership when mutating shared nodes.
- Using linked lists where indexed access dominates.
Execution guardrailQuick-Start Checklist
- Identify head and tail behavior.
- Separate traversal cost from rewiring cost.
- Save references before mutation.
- Handle empty and single-node lists.
- State pointer overhead and locality trade-offs.
Recall drillKnowledge Check
| Question | Strong answer |
|---|---|
| Why is random access O(n)? | You must follow next references from head until the target position. |
| When is insertion O(1)? | When the insertion point node is already known. |
| Why does LRU combine map plus list? | The map gives lookup; the list gives O(1) recency rewiring. |
VocabularyKey Terms
| Term | Meaning |
|---|---|
| Node | A value plus reference fields. |
| Head | The first node reference. |
| Next pointer | A reference to the following node. |
| Doubly linked list | Nodes with prev and next references. |
Next practiceFurther Reading
- Practice merge two sorted lists and remove nth node from end.
- Study LRU cache after linked-list mutation is comfortable.
- Compare linked lists with dynamic arrays in language runtimes.