Reverse a linked list
Three pointers and one saved link. The question that checks you can move pointers without losing the rest of the list.
- Write an iterative linked-list reversal with O(1) extra space.
- Predict prev, cur and next at each step of a dry run.
- Fix the bug of overwriting Next before saving it.
The problem
Given the head of a singly linked list, reverse it and return the new head. 1 → 2 → 3 becomes 3 → 2 → 1.
Brute force first
Walk the list and copy every value into a slice. Walk it again and write the values back from the end of the slice.
O(n) time, O(n) extra space. It also only swaps values, not nodes, which some interviewers will not accept.
The approach
Walk the list once. For each node, save its Next, point it back at the previous node, then step forward. When you fall off the end, prev is the new head. O(n) time, O(1) space.
A recursive version exists, but it uses O(n) stack. Offer it only if asked.
package mainimport "fmt"type Node struct { Val int Next *Node}// reverse flips the links one node at a time and returns the new head.func reverse(head *Node) *Node { var prev *Node for cur := head; cur != nil; { next := cur.Next // save it before we overwrite the link cur.Next = prev prev, cur = cur, next } return prev}func build(vals ...int) *Node { var head *Node for i := len(vals) - 1; i >= 0; i-- { head = &Node{Val: vals[i], Next: head} } return head}func show(n *Node) { for ; n != nil; n = n.Next { fmt.Print(n.Val, " ") } fmt.Println()}func main() { show(reverse(build(1, 2, 3, 4, 5))) // 5 4 3 2 1 show(reverse(build(7))) // 7 show(reverse(nil)) // (empty line)}Dry run
1 → 2 → 3. Each row is one loop iteration:
| step | next (saved) | cur.Next set to | prev after | cur after |
|---|---|---|---|---|
| start | - | - | nil | 1 |
| 1 | 2 | nil | 1 | 2 |
| 2 | 3 | 1 | 2 | 3 |
| 3 | nil | 2 | 3 | nil |
| end | cur is nil, return prev | 3 → 2 → 1 |
Go-specific gotchas
- Save `Next` before you overwrite it. Once
cur.Next = prevruns, the rest of the list is gone unless you kept a pointer to it. - **A nil
*Nodeis a valid empty list.**var prev *Nodestarts as nil, and the loop simply does not run for a nil head. No special case needed. - Tuple assignment
prev, cur = cur, nextevaluates the right side first, so the order is safe. - Go has
container/list, but interviewers want your ownNodetype for this one.
- Three pointers:
prev,cur, and the savednext. - Save the link before you break it.
- Return
prev, notcur.curis nil at the end.
m and n (1-based) and leave the rest in place.reverseList(head *Node) *Node that reverses a singly linked list by relinking the existing nodes (no new nodes) and returns the new head. Example: 1 → 2 → 3 → 3 → 2 → 1. An empty list stays nil.Tab indents. Press Esc, then Tab, to leave the editor.
- 1The main task: Reverse only the nodes between positions
mandn(1-based) and leave the rest in place. - 2Dry run the loop on a one-node list
5. How many iterations, and what is returned? - 3Check whether a linked list is a palindrome (
1 → 2 → 2 → 1is) in O(n) time and O(1) extra space.