Module P-2·18 min read

Node-based structures, singly vs doubly linked lists, and the reversal/cycle-detection operations every list problem builds on.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module P-2 — Linked Lists: Singly, Doubly, and Core Operations

What this module covers: Every structure so far in this course has been array-backed — one contiguous block of memory (Module F-2). A linked list breaks that assumption: each element is its own independently allocated node, connected by pointers rather than physical adjacency. This module covers singly and doubly linked lists, why insertion/deletion trade places with arrays on cost, reversal, and the cycle-detection technique previewed in Module F-8, now applied directly.


A Node-Based Structure

Where an array is one block with elements at predictable offsets, a linked list is a chain of individually allocated nodes, each holding a value and a pointer to the next node:

typescript

There is no address = base + i × size arithmetic here (Module F-2) — to reach the third node, you have to follow head.next.next, visiting each node in between. That's the fundamental trade: array indexing is O(1); linked list indexing (or "get the k-th element") is O(n).

Analogy: An array is the apartment building from Module F-2 — walk straight to unit 47. A linked list is a treasure hunt where each clue only reveals the location of the next clue — you cannot skip to clue 47 without having followed clues 1 through 46 first.


Where Linked Lists Win

The trade runs the other way for insertion and deletion at a known position. Inserting into the middle of an array means shifting every subsequent element (Module F-2); inserting into a linked list is just pointer reassignment — no other node moves at all:

typescript

This is genuinely O(1), regardless of how long the list is — a real, meaningful advantage over an array's O(n) middle-insertion cost, provided you already have a reference to the node you're inserting after. Finding that node in the first place is still O(n) if you don't already have a pointer to it, which is the honest caveat behind "linked lists have O(1) insertion" — it's O(1) insertion at a known point, not O(1) insertion at an arbitrary position you still have to search for.


Singly vs Doubly Linked Lists

A singly linked list (above) only points forward — from a given node, you can reach the next one, but not the previous one. A doubly linked list adds a prev pointer too:

typescript

The extra pointer costs a small amount of memory per node, but it buys something a singly linked list can't do cheaply: deleting a node in O(1), given only a reference to that node — no need to separately track or search for its predecessor, because the node already knows who it is:

typescript

In a singly linked list, deleting a given node requires first finding its predecessor by traversing from the head — O(n) — specifically because there's no prev pointer to jump backward through. This exact capability — O(1) deletion of an arbitrary known node — is the reason Module P-3's LRU Cache is built on a doubly linked list, not a singly linked one.


Reversing a Linked List

Reversal is the linked-list equivalent of Module F-2's array reversal, but the mechanism is entirely different — instead of swapping values in place, you re-point every next pointer to face the other direction:

typescript

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.