Linked List is one of the most fundamental data structures in computer science and a must-know topic for coding interviews.
Unlike arrays, linked lists don’t require you to predefine a size.
They allocate memory dynamically as elements are added. And because each element points to the next, you can insert or remove nodes without shifting anything which makes them extremely flexible for certain use cases.
In this chapter, I’ll break down:
So… what exactly is a linked list?
A linked list is a linear data structure made up of nodes.
Each node contains two parts:
The last node points to null, indicating end of the list.
Unlike arrays, where all elements are stored together in a single, continuous block of memory, the nodes in a linked list can be scattered across memory.
Arrays (Contiguous Memory Allocation)
Linked List (Dynamic Memory Allocation)
What keeps them connected are those pointers linking one node to the next.
This structure makes linked lists highly flexible. You can grow or shrink them dynamically, and insertions or deletions don’t require shifting large chunks of memory like arrays do.
But this flexibility comes with a trade-off.
Instead, to access the 5th or 10th element, you may have to traverse the list from the beginning, one node at a time, which takes linear time.
Not all linked lists are the same. Depending on how the nodes are connected, we can categorize them into three common types:
Let’s break them down one by one.
In a singly linked list, each node contains a value and a pointer to the next node and that’s it.
You can only move in one direction, from the head toward the tail.
Singly linked lists are great for problems where you only need forward traversal.
A doubly linked list takes things one step further.
Each node has two pointers:
This means you can move forward and backward, which makes certain operations much more efficient.
But the trade-off is that it uses extra memory to store the additional pointer and it introduces a bit more complexity in updating links during insertions or deletions.
Doubly linked lists are widely used in real-world systems like: LRU caches, text editors for undo/redo functionality, and browser history navigation.
and finally, circular linked list.
A circular linked list is a variation where the last node points back to the first node, instead of null.
This forms a loop. You can start at any node and keep going until you're back where you started.
It’s great for problems where you need cyclical behavior like round-robin scheduling, or multiplayer games where turns cycle through players
Now that we know what linked lists are and the different types, let’s go over the most common operations you’ll perform on them.
Traversal means moving through the list, visiting each node one by one. You start at the head and move one node at a time.
This operation takes O(n) time because, in the worst case, you might visit every node.
If you want to find whether a value exists in a linked list, you must:
Since this is a linear search, it takes O(n) time in the worst case.
Linked lists really shine when it comes to insertion because you don’t have to shift elements like you would in an array.
There are different cases depending on where you are inserting a node:
Insert at the Beginning
This is the fastest case.
All you need to do is:
next to the current headIt takes constant time since no traversal is needed.
Insert at the End
To insert at the end, you have to:
next to the new nodeIf you maintain a tail pointer, you can insert in constant time O(1). Otherwise, you’ll need to traverse the entire list to find the last node, which takes O(n) time.
Insert at a Given Position
To insert at a specific position (say after the 5th node), you must:
Again, this requires O(n) time in the worst case.
Like insertion, deletion can also vary based on position.
Delete from the Beginning
This is fast. Just move the head pointer to the next node:
This is constant time since no traversal is needed.
Delete from the End or Middle
To delete the last node or a node in the middle:
next pointer to skip the node you want to deleteSince there's no backward pointer in a singly linked list, this means traversing from the head — which takes O(n) time.
Here’s a summary of the time complexities of various operations in a linked list:
Operation | Time Complexity |
|---|---|
Traverse |
|
Search |
|
Insert at start |
|
Insert at end |
|
Insert at index |
|
Delete from start |
|
Delete from end |
|
Now let’s talk about some of the most frequent linked list patterns that show up in coding interviews.
Also known as Floyd’s Tortoise and Hare algorithm. Here’s how it works:
You use two pointers:
This simple trick allows you to solve problems like:
This is a must-know technique in interviews.
The challenge is to reverse the direction of pointers so the last node becomes the new head.
We can do it in-place by maintaining three pointers at previous, current and next node.
And then walking through the list and flipping the pointers one by one.
Another common trick is using dummy nodes. This one’s a clean code technique that makes your implementation simpler and less error-prone.
A dummy node is just a placeholder node that you insert before the real head of the list.
It eliminates messy special cases like:
With a dummy node, you treat the head like any other node — so your logic stays uniform and your code gets much cleaner.