Linked Lists
Data Structures·beginner·~35 min read
- linked-list
- data-structure
- fundamentals
A linked list is a linear data structure where elements are stored in nodes, and each node contains a reference (pointer) to the next node in the sequence. Unlike arrays, linked list elements are not stored in contiguous memory locations…
What you'll learn
Node Structure
Every linked list is built from nodes. A node is the fundamental building block: - data: The value stored in the node (integer, string, object, etc.) - next: A pointer/reference to the next node in the list In code, a node looks like: Th…
Memory Allocation
Linked lists use non-contiguous, heap-allocated memory: Each node is independently allocated on the heap. This means: - Nodes can be anywhere in memory - No need to declare size upfront - No wasted pre-allocated space - But no cache-line…
Singly Linked List
The most basic form. Each node points to the next node, and the last node points to null.
Visual Representation
Operations with Diagrams
Doubly Linked List
Each node has pointers to both the next AND previous nodes, enabling bidirectional traversal.
Node Structure
Visual Representation
Insert in Doubly Linked List
Delete in Doubly Linked List
Complexity: O(1) time with a direct node reference, O(1) space. When you have a pointer to the node, both neighbors are instantly accessible via prev and next. In a singly linked list, you would need O(n) traversal to find the previous n…
When to Prefer Doubly Over Singly
- When you need backward traversal (e.g., browser history back/forward) - When deletion is frequent and you have direct node references (e.g., LRU cache) - When implementing deques (double-ended queues) - When you need to traverse a wind…
Space Overhead
- Singly linked list: 1 extra pointer per node - Doubly linked list: 2 extra pointers per node For a node storing a 4-byte integer on a 64-bit system: - Array: 4 bytes per element - Singly: 4 + 8 = 12 bytes per element (50% overhead) - D…
Circular Linked List
The last node points back to the first node, forming a cycle.
Singly Circular
Doubly Circular
Use Cases
1. Round-robin scheduling: Process scheduler cycles through tasks endlessly 2. Circular buffers: Audio streaming, network packet buffers 3. Multiplayer games: Turn rotation among players 4. Carousel/slideshow: Cycling through items with…
Complete Time Complexity Table
| Operation | Singly | Doubly | Why | |-----------|--------|--------|-----| | Access by index | O(n) | O(n) | No random access; must traverse from head | | Search | O(n) | O(n) | Must check nodes sequentially | | Insert at head | O(1) |…
Space Complexity
- Overall: O(n) for n elements - Per node overhead: - Singly: +1 pointer (8 bytes on 64-bit) - Doubly: +2 pointers (16 bytes on 64-bit)
Common Patterns and Algorithms
1. Runner Technique (Fast/Slow Pointers)
Use two pointers moving at different speeds to solve cycle detection, find midpoints, and more. Find middle of list: Sample Input / Output Input: head = 1 → 2 → 3 → 4 → 5 Output: 3 (middle node) Input: head = 1 → 2 → 3 → 4 Output: 3 (mid…
2. Linked List Reversal
Reverse the direction of all pointers. Sample Input / Output Input: head = 1 → 2 → 3 → 4 → 5 Output: 5 → 4 → 3 → 2 → 1 Input: head = 1 → 2 Output: 2 → 1 Input: head = null Output: null (empty list — edge case) Complexity: O(n) time, O(1)…
3. Merge Two Sorted Lists
Combine two sorted linked lists into one sorted list. Sample Input / Output Input: l1 = 1 → 3 → 5, l2 = 2 → 4 → 6 Output: 1 → 2 → 3 → 4 → 5 → 6 Input: l1 = null, l2 = 1 → 2 → 3 Output: 1 → 2 → 3 (one list empty — edge case) Input: l1 = 1…
4. Detect and Find Cycle Start
Sample Input / Output Input: 1 → 2 → 3 → 4 → 5 → (back to 3) (node 5's next points to node 3) Output: node with value 3 — the start of the cycle. Input: 1 → 2 → 3 → null Output: null — no cycle. Input: 1 → (back to 1) (single node pointi…
5. Remove N-th Node From End
Sample Input / Output Input: list 1 → 2 → 3 → 4 → 5, n = 2 Output: 1 → 2 → 3 → 5 (removed node 4, the 2nd from the end). Input: list 1, n = 1 Output: null (removed the only node — the dummy makes this a normal case). Input: list 1 → 2, n…
When to Use Linked Lists
Use linked lists when:
1. Frequent insertions/deletions at arbitrary positions -- O(1) with node reference vs. O(n) shifting in arrays 2. Size is unknown or highly variable -- no need to resize or pre-allocate 3. Implementing stacks -- push/pop at head is O(1)…
Do NOT use linked lists when:
1. You need random access -- accessing element at index i is O(n), not O(1) 2. Cache performance matters -- non-contiguous memory causes cache misses 3. Memory overhead is a concern -- extra 8-16 bytes per element for pointers 4. You nee…
Comparison: Linked List vs Array
| Criteria | Array | Linked List | |----------|-------|-------------| | Access by index | O(1) | O(n) | | Insert at beginning | O(n) | O(1) | | Insert at end | O(1) amortized | O(1) with tail | | Insert at middle | O(n) | O(1) if positio…
Competitive Programming Patterns
Pattern 1: Sentinel/Dummy Nodes
Sample Input / Output Input: merge sorted lists 1 → 3 → 5 and 2 → 4 → 6 Output: 1 → 2 → 3 → 4 → 5 → 6 Input: delete target 3 from 1 → 3 → 5 → 7 Output: 1 → 5 → 7 Input: delete target 1 from 1 → 2 → 3 Output: 2 → 3 (head deletion without…
Pattern 2: In-place Reversal (Sublist)
Sample Input / Output Input: list 1 → 2 → 3 → 4 → 5, left = 2, right = 4 Output: 1 → 4 → 3 → 2 → 5 — nodes at positions 2..4 reversed, endpoints untouched. Input: list 1 → 2 → 3 → 4 → 5, left = 1, right = 5 Output: 5 → 4 → 3 → 2 → 1 (ent…
Pattern 3: Partition Around a Value
Sample Input / Output Input: list 1 → 4 → 3 → 2 → 5 → 2, x = 3 Output: 1 → 2 → 2 → 4 → 3 → 5 — all = 3 (also preserving order). Input: list 3 → 5 → 8, x = 2 Output: 3 → 5 → 8 (all nodes >= x — edge case) Input: list 1 → 2, x = 5 Output:…
Pattern 4: Recursive Approach
Sample Input / Output (recursive reverse) Input: 1 → 2 → 3 → 4 → 5 Output: 5 → 4 → 3 → 2 → 1 Input: 1 → 2 Output: 2 → 1 Input: 1 Output: 1 (single node base case — edge case) Many linked list problems have elegant recursive solutions. Co…
Pattern 5: Fast/Slow + Reverse Half (Composite Pattern)
Sample Input / Output Palindrome check: - Input: 1 → 2 → 3 → 2 → 1 → Output: true - Input: 1 → 2 → 3 → 4 → Output: false Reorder list (L0→Ln→L1→Ln-1→…): - Input: 1 → 2 → 3 → 4 → 5 → Output: 1 → 5 → 2 → 4 → 3 Several problems combine find…
6. Clone a Linked List with Random Pointers
Sample Input / Output Input (each node is (value, randomtargetindex) where randomtargetindex = -1 means null): The next chain is 7 → 13 → 11 → 10 → 1; random pointers: 7→null, 13→7, 11→1, 10→11, 1→7. Output: an independent deep copy with…
Summary of Key Insights
1. Linked lists trade random access for efficient insertion/deletion 2. The pointer overhead is the cost of flexibility 3. Doubly linked lists trade more memory for O(1) deletion with node reference 4. Fast/slow pointer technique is the…