Topics › Linked List › Learn 1D LinkedList
Find the length of the Linked List
Java source ↗ Edit this article ↗
Jump to code:
Problem
You are given the head of a singly linked list. Return the number of nodes in it. The empty list (a null head) has length 0.
Constraints: 0 ≤ n ≤ 10^5 nodes, values fit in a 32-bit signed integer. The list has no cycle, so a traversal always terminates.
Example 1
list = 1 -> 2 -> 3 -> 4 -> 5
answer = 5
Example 2
list = (empty)
answer = 0 // a null head means no nodes
Example 3
list = 3 -> 3 -> 3
answer = 3 // equal values are still separate nodes
The node type is the standard one with an int val and a ListNode next reference.
static class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
Approach 1: Walk and count
Intuition. Unlike an array, a linked list does not store its own size. The only way to learn how many nodes there are is to visit them. A traversal that increments a counter on every node and stops at null is the whole algorithm; it is the first “real” loop you write on a linked list and the template for every traversal after it.
Algorithm.
- Set
count = 0andtemp = head. - While
temp != null: incrementcountand movetemptotemp.next. - Return
count.
static int lengthIterative(ListNode head) {
int count = 0;
ListNode temp = head;
while (temp != null) {
count++;
temp = temp.next;
}
return count;
}
Complexity. Time O(n): every node is visited exactly once. Space O(1): a counter and one reference.
Dry run on 1 -> 2 -> 3:
| iteration | temp | count after |
|---|---|---|
| start | [1] |
0 |
| 1 | [2] |
1 |
| 2 | [3] |
2 |
| 3 | null |
3 |
The loop condition is checked with temp on null after the third node, so the loop ends with count = 3. On an empty list the body never runs and 0 is returned without any special case. Note that the walk uses a temporary reference temp; writing head = head.next would work inside this method (Java passes the reference by value, so the caller’s variable is safe) but it is a bad habit, because in methods that must return the list it destroys the handle you need.
Approach 2: Recursion
Intuition. A linked list has a naturally recursive shape: it is either empty, or a node followed by a smaller list. The length follows the same shape. The empty list has length 0; any other list has length 1 + (length of the rest). Writing that down directly gives a two-line function that is useful to understand because many later problems (reversing recursively, checking a palindrome, flattening) use the same decomposition.
Algorithm.
- If
head == null, return0. - Otherwise return
1 + lengthRecursive(head.next).
static int lengthRecursive(ListNode head) {
if (head == null) return 0;
return 1 + lengthRecursive(head.next);
}
Complexity. Time O(n), one call per node. Space O(n) for the call stack, because each pending 1 + ... has to wait for the call below it to return.
That stack cost is the reason the iterative version is preferred in practice. The default Java thread stack comfortably handles a few thousand frames (the tests use a 5000-node list), but a list of 10^5 nodes is likely to throw StackOverflowError. Recursion here is a teaching device, not a production choice; whenever a recursive linked-list algorithm is “tail recursive”, the loop version is what you should actually write.
Approach 3: Keep the size up to date
Intuition. If the length is asked for often, paying O(n) every time is wasteful. The alternative is to store a size field alongside the head and adjust it on every insertion and deletion. Each of those operations already costs at least O(1), so adding one increment or decrement does not change their complexity, while length() drops to O(1). This is exactly how java.util.LinkedList and ArrayList work: size() is a field read.
Algorithm.
- Wrap the head in a small class with an
int size. addFirstcreates a node in front of the head and doessize++.removeFirstmoves the head forward and doessize--, doing nothing on an empty list.length()returnssize.
static class SizedList {
ListNode head;
int size;
void addFirst(int val) {
head = new ListNode(val, head);
size++;
}
void removeFirst() {
if (head == null) return;
head = head.next;
size--;
}
int length() { return size; }
}
Complexity. length() is O(1) time. addFirst and removeFirst remain O(1). Space O(1) extra for the field.
The price is an invariant to maintain: size must equal the true number of nodes after every operation. If any code path modifies the links without updating size (for example, someone splices nodes in by hand), the field silently drifts. The tests guard against this by comparing list.length() with lengthIterative(list.head) after every sequence of operations. A good rule is that the links should only ever be touched through methods of the wrapper class, so there is exactly one place where each link change and its matching size change live together.
Choosing between them
| Iterative | Recursive | Size field | |
|---|---|---|---|
| Time per query | O(n) |
O(n) |
O(1) |
| Extra space | O(1) |
O(n) stack |
one int |
| Works on a bare head reference | yes | yes | no, needs the wrapper |
| Risk | none | stack overflow on long lists | stale size if links are edited directly |
When a problem hands you only a ListNode head, Approach 1 is the answer. When you are designing a list class, Approach 3 is what users will expect from size(). Approach 2 is the one to understand rather than use.
Edge cases and pitfalls
- Empty list.
head == nullmust return0. Both the loop and the recursion handle it because the first thing they do is test fornull. - Single node. Length
1; the loop runs once, the recursion makes one real call plus the base case. - Duplicates. Count nodes, not distinct values.
[3, 3, 3]has length3. - Cycles. If the list contained a cycle, both counting methods would loop forever. The problem guarantees there is none; detecting one is a separate problem solved with the tortoise-hare method.
- Deep recursion.
lengthRecursiveon10^5nodes risksStackOverflowError. Use the loop for long inputs. - Size drift. With a size field, every link mutation must be paired with a size update. Never let callers reach the links directly.
- Overflow.
intis enough for any list that fits in memory; a list of more than2^31 - 1nodes would need hundreds of gigabytes.
Related problems
- Introduction to Singly LinkedList introduces the node type and the traversal pattern used here.
- Search in Linked List is the same traversal with an early exit.
- Middle of a LinkedList [TortoiseHare Method] shows how to find the middle without counting first.
- Remove Nth node from the back of the LL uses the length to convert a position from the back into a position from the front.
- Length of loop in LL counts nodes in a list that does contain a cycle.