Swap Nodes in Pairs: Pairwise Linked List Manipulation
Swap Nodes in Pairs is LeetCode problem 24. Given a linked list, swap every two adjacent nodes and return the new head. You cannot modify the node values. You can only change the nodes themselves.
This is a medium problem, but the logic is surprisingly tight. You need to rewire three pointers per pair without losing your place in the list. Getting the order of assignments wrong means broken links or infinite loops.
The problem
Given a linked list, swap every two adjacent nodes and return its head.
Example: 1 -> 2 -> 3 -> 4 becomes 2 -> 1 -> 4 -> 3.
Constraints: you must not modify the values in the nodes. Only the nodes themselves may be changed. This means you cannot cheat by swapping values between two nodes. You need to actually rewire the next pointers.
Why the head changes
The first thing to notice is that the head of the list changes after swapping. Node 2 becomes the new head. That means your function needs to return a different node than the one it received.
This is a classic situation where a dummy head (also called a sentinel node) makes life easier. You create a temporary node that points to the head of the list. After all the swaps are done, you return dummy.next. This eliminates the special case of handling the head separately.
The iterative approach (dummy head + rewire pairs)
The idea is simple. Walk the list in steps of two. For each pair, rewire the pointers so the second node comes before the first. A prev pointer tracks the node just before the current pair, so you can stitch the swapped pair back into the rest of the list.
For each pair, you have three nodes involved:
- prev - the node before the current pair
- first - the first node in the pair (
prev.next) - second - the second node in the pair (
first.next)
The three rewiring steps for each pair:
first.next = second.next- first now skips over second and points to whatever comes after the pairsecond.next = first- second now points back to firstprev.next = second- the previous node now points to second (which is the new front of the pair)
After these three assignments, the pair is swapped. Move prev forward to first (which is now the second node in the swapped pair) and repeat.
Visual walkthrough
Trace through swapping pairs in 1 -> 2 -> 3 -> 4. The dummy node (labeled "d") sits in front of the list. Watch how prev advances two nodes at a time, swapping each pair as it goes.
Setup: Create a dummy node before the head. prev = dummy.
dummy.next = head. first = prev.next (node 1). second = first.next (node 2).
Swap pair 1: Rewire pointers so node 2 comes before node 1.
prev.next = second (2), first.next = second.next (3), second.next = first (1). Then advance: prev = first (now at position of 1), identify next pair.
Swap pair 2: Rewire pointers so node 4 comes before node 3.
Same three assignments: prev.next = second (4), first.next = second.next (null), second.next = first (3). prev advances to node 3.
Done: prev.next is null, so no more pairs. Return dummy.next.
The list is now 2 -> 1 -> 4 -> 3 -> null. Every pair has been swapped.
Notice the symmetry. Every pair swap uses the exact same three pointer assignments. The dummy head means there is no special case for the first pair.
The iterative solution
def swapPairs(head):
dummy = ListNode(0)
dummy.next = head
prev = dummy
while prev.next and prev.next.next:
first = prev.next
second = first.next
first.next = second.next
second.next = first
prev.next = second
prev = first
return dummy.next
The loop condition prev.next and prev.next.next checks that there are at least two nodes remaining to form a pair. If there is zero or one node left, we stop. An odd-length list leaves the last node untouched, which is the correct behavior.
The order of the three pointer assignments matters. If you set prev.next = second before first.next = second.next, you lose the reference to the rest of the list. Always update first.next first, since that saves the link to nodes after the pair.
The recursive solution
The recursive approach is more compact. The idea: swap the first two nodes, then recursively swap the rest of the list and attach it.
def swapPairs(head):
if not head or not head.next:
return head
first = head
second = head.next
first.next = swapPairs(second.next)
second.next = first
return second
Here is what happens:
- Base case: If there are fewer than two nodes, return the head as-is.
- Identify the pair:
firstis the current head,secondis the node after it. - Recurse: Swap all remaining pairs starting from
second.next. Attach the result tofirst.next. - Swap: Point
second.nexttofirst, makingsecondthe new front of this pair. - Return:
secondis the new head of this portion of the list.
The recursive version is elegant, but it uses O(n) stack space. For interview purposes, the iterative version is usually preferred because it runs in O(1) space.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Iterative (dummy head) | O(n) | O(1) |
| Recursive | O(n) | O(n) |
Both approaches visit each node exactly once. The iterative version only uses a few pointer variables. The recursive version adds a stack frame for every pair, which means O(n/2) = O(n) space.
Edge cases
- Empty list (head is null). The loop condition fails immediately.
dummy.nextis null. Return null. Correct. - Single node.
prev.nextexists butprev.next.nextis null. The loop does not run. The single node is returned unchanged. Correct. - Odd-length list like
1 -> 2 -> 3. The first pair (1, 2) swaps to produce2 -> 1 -> 3. Thenprevis at node 1,prev.nextis 3, butprev.next.nextis null. The loop stops. Node 3 stays in place. Correct. - Two nodes. The minimal case where a swap actually happens.
1 -> 2becomes2 -> 1. Good for verifying your logic by hand.
The Building Blocks
This problem is built from two core building blocks:
Pairwise pointer rewiring. You take two adjacent nodes and swap their positions by rewiring three next pointers in a specific order. This is a localized version of the reversal technique from Reverse Linked List. Instead of reversing the entire chain, you reverse exactly two nodes at a time. The same principle applies: save what you are about to overwrite before making the change.
Dummy head (sentinel node). When the head of a list might change, inserting a dummy node before it gives you a stable anchor point. You never need to special-case the first pair because prev starts at the dummy node, and the same three-step rewiring works uniformly. This pattern shows up in many linked list problems, including Remove Nth Node From End and Merge Two Sorted Lists.
Swap Nodes in Pairs is a specific case of Reverse Nodes in k-Group (LeetCode 25) with k = 2. If you can swap pairs cleanly, you are halfway to solving the k-group version. The generalization replaces the fixed three-pointer swap with a loop that reverses k nodes at a time.
From understanding to recall
You understand the three pointer assignments. You can trace through the diagram. But can you type this solution from scratch in under three minutes?
The failure mode is not forgetting the idea. It is getting the order of the three assignments wrong. Did prev.next get updated before or after first.next? Which pointer do you advance at the end of the loop, first or second?
These details are the difference between a working solution and a five-minute debugging session on a whiteboard. The only way to make them automatic is repetition. Type the solution from memory today, again in two days, again in a week. By the fourth rep, the three-step pattern is muscle memory.
Related posts
- Reverse Linked List - The foundational pointer reversal technique that this problem builds on
- Reorder List - Another problem that requires careful pointer rewiring across multiple phases