206. Reverse Linked List
easyAsked at TwilioReverse Linked List is Twilio's pointer-mechanics warm-up: flip a singly-linked list in place and return the new head. The grading bar is whether you write the iterative three-pointer version correctly the first try, with bonus credit for a clean recursive version.
By Sam K., Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Twilio loops.
- Glassdoor (2026-Q1)— Heavily-cited in Twilio phone-screen reports — often paired with Merge Two Sorted Lists.
- LeetCode Discuss (2025-11)— Listed across Twilio backend SWE interview reports.
Problem
Given the head of a singly linked list, reverse the list, and return the reversed list.
Constraints
The number of nodes in the list is the range [0, 5000].-5000 <= Node.val <= 5000
Examples
Example 1
head = [1,2,3,4,5][5,4,3,2,1]Example 2
head = [1,2][2,1]Example 3
head = [][]Approaches
1. Collect values to array, rebuild (rejected)
Walk the list to collect values, build a new list from the reversed array.
- Time
- O(n)
- Space
- O(n)
function reverseListBrute(head) {
const vals = [];
let curr = head;
while (curr) { vals.push(curr.val); curr = curr.next; }
vals.reverse();
const dummy = { val: 0, next: null };
let tail = dummy;
for (const v of vals) { tail.next = { val: v, next: null }; tail = tail.next; }
return dummy.next;
}Tradeoff: O(n) extra space and allocates new nodes. Twilio rejects this immediately — the problem expects in-place pointer manipulation.
2. Iterative three-pointer (optimal)
Walk the list, flipping each node's next pointer to its predecessor.
- Time
- O(n)
- Space
- O(1)
function reverseList(head) {
let prev = null;
let curr = head;
while (curr) {
const next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}Tradeoff: Three pointers: prev (the new tail-of-reversed), curr (the node being flipped), next (saved before mutation). The 'save next first' ordering is the entire trick — get it wrong and you orphan the rest of the list.
3. Recursive reversal (clean variant)
Recurse to the end, then unwind by flipping each node.next.next = node.
- Time
- O(n)
- Space
- O(n) recursion stack
function reverseListRecursive(head) {
if (head === null || head.next === null) return head;
const newHead = reverseListRecursive(head.next);
head.next.next = head; // flip the next node's pointer back to current
head.next = null; // current becomes the new tail
return newHead;
}Tradeoff: More elegant but O(n) stack space. For n = 5000 in JS the recursion is safe; in environments with tight stack limits, iterative wins. Bonus credit at Twilio for offering both.
Twilio-specific tips
Twilio's grading bar on Reverse Linked List is whether you write the iterative version without bugs the first try. Walk through the pointer state on a 3-node example before coding — interviewers explicitly look for that pre-coding trace. Mention the recursive version too: 'I'll write iterative for O(1) space; the recursive version is clean if you don't mind O(n) stack.' That signals you know both idioms.
Common mistakes
- Forgetting to save `next` before reassigning `curr.next` — orphans the rest of the list and you only return the first node.
- Returning `head` instead of `prev` — at loop exit, head still points at the original (now last) node; prev is the new head.
- Setting head.next = null in the recursive variant in the wrong order — must happen AFTER head.next.next = head.
Follow-up questions
An interviewer at Twilio may pivot to one of these next:
- What if you needed to reverse only nodes between positions left and right (LC 92)? (Walk to position left, then run the same flip for right - left + 1 iterations, splice back.)
- What if you needed to reverse the list in groups of K (LC 25)? (Repeated apply of the segment-reverse with a tail pointer to splice each reversed group.)
- How would you detect if a list is a palindrome using this technique? (Reverse the second half, walk both halves in parallel.)
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why is `prev = null` the correct initial value?
Because the original head becomes the new tail, and a tail's next pointer is null. Starting prev as null means the first iteration sets head.next = null, which is exactly what we want.
Why is the recursive version's `head.next = null` necessary?
Because without it, the original head still points forward to its old successor — creating a cycle once head.next.next = head executes. Setting it to null breaks that cycle and makes head the new tail.
Free learning resources
Curated free links for this problem.