MediumLinked List

Swap Nodes in Pairs โ€” Solution

Problem

Given a linked list, swap every two adjacent nodes and return the new head. You must rearrange the nodes themselves โ€” not their values โ€” so this is a pure pointer manipulation problem.

1
โ†’
2
โ†’
3
โ†’
4
โ†’โˆ…
[1,2,3,4]
  • Input: head = [1, 2, 3, 4]
  • Output: [2, 1, 4, 3]
  • Explanation: Node 2 swaps with Node 1, then Node 4 swaps with Node 3.

If the list has an odd number of nodes, the last unpaired node stays in place.

  • Input: head = [1, 2, 3]
  • Output: [2, 1, 3]

Intuition

Each swap only touches two nodes at a time: the second node in the pair becomes the new head of that pair, and the first node falls behind it. The tricky part is that the node before the pair must update its next pointer to the new pair head โ€” a dummy head node makes this uniform across all pairs, including the very first one.

Approach 1 โ€” Recursive

Think of the problem as: swap the first two nodes, then recursively solve the rest and attach the result to the first node's next.

  1. Base case: if fewer than two nodes remain, return head unchanged.
  2. Label the first node first and the second node second.
  3. Recursively call on second.next to get the already-swapped tail.
  4. Set second.next = first to reverse the current pair.
  5. Set first.next to the processed tail.
  6. Return second as the new head of this pair.
1class Solution:
2    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
3        if not head or not head.next:
4            return head
5
6        first = head
7        second = head.next
8
9        # recurse before relinking so the tail isn't lost when we rearrange pointers
10        remaining = self.swapPairs(second.next)
11
12        second.next = first
13        first.next = remaining
14
15        return second

Time: O(n) โ€” each node is visited exactly once across all recursive calls.
Space: O(n) โ€” the call stack grows to n/2 frames deep for n nodes.

Approach 2 โ€” Iterative with Dummy Head

Use a sentinel node before the list so every pair always has a predecessor to update. Walk prev forward by two nodes each iteration.

  1. Create a dummy node pointing to head; set prev = dummy.
  2. While prev.next and prev.next.next both exist (at least two nodes remain):
  3. Save first = prev.next, second = prev.next.next.
  4. Set first.next = second.next โ€” detach first from second, bridging over it.
  5. Set second.next = first โ€” second now leads the pair.
  6. Set prev.next = second โ€” attach the predecessor to the new pair head.
  7. Advance prev = first โ€” first is now the tail of the swapped pair.
  8. Return dummy.next.
1class Solution:
2    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
3        dummy = ListNode(0, head)
4        prev = dummy
5
6        while prev.next and prev.next.next:
7            first = prev.next
8            second = prev.next.next
9
10            first.next = second.next   # first jumps over second to what comes after
11            second.next = first        # second points back at first, completing the swap
12            prev.next = second         # predecessor now leads into the swapped pair
13
14            prev = first               # first is the new tail; advance prev to it
15
16        return dummy.next

Time: O(n) โ€” each node is visited exactly once.
Space: O(1) โ€” only a constant number of extra pointers regardless of list length.

Complexity Summary

ApproachTimeSpaceWhen to use
RecursiveO(n)O(n)When clarity matters more than stack depth; fine for short lists
Iterative (Dummy Head)O(n)O(1)Production code or when stack overflow risk is a concern

Common Mistakes

  • Advancing prev to the wrong node โ€” after swapping, first becomes the tail of the pair, so prev must advance to first, not second. Advancing to second revisits already-swapped nodes and produces wrong output.
  • Doing the pointer updates in the wrong order โ€” you must save the rest of the list in first.next = second.next before setting second.next = first. Reversing these two lines loses the tail permanently.
  • Omitting the dummy head โ€” without a dummy node, the list head changes after the first swap, requiring a special case. The dummy makes all iterations identical.
  • Incomplete base case in recursion โ€” checking only if not head (missing not head.next) crashes on an odd-length list when one node remains with no pair.
  • Returning dummy instead of dummy.next โ€” the sentinel node has value 0 and should never appear in the output; always return dummy.next.

Related Problems

  • reverse-nodes-in-k-group โ€” generalizes this problem to reversing groups of k nodes instead of 2
  • reverse-linked-list โ€” the core pointer-reversal skill that this problem directly builds on
  • odd-even-linked-list โ€” rearranges nodes by odd/even position, requiring similar multi-pointer bookkeeping
  • reorder-list โ€” rearranges a linked list end-to-end with the same style of careful pointer manipulation
  • rotate-list โ€” another problem requiring precise pointer tracking across the full list

Ready to practice? Try it on SkillFlow

Adaptive problems, AI follow-up interviews, and a skill score that shows exactly where you need to improve.

Practice This Problem โ†’