LeetCode #24 Medium

Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return the new head. You must swap the nodes themselves, not just their values.

linked-listrecursion
Open on LeetCode ↗
02

Intuition

For each pair of nodes A -> B, you want B -> A, and A should point to whatever the next pair's swap produces. A dummy node before the head avoids special-casing the first pair. Walk with a prev pointer that always sits right before the next pair to swap. The pointer surgery for each pair is three reassignments: prev.next = B, A.next = B.next, B.next = A. Then advance prev to A (which is now the second node of the swapped pair) and repeat.

How to spot this pattern

When a linked list problem asks you to rearrange nodes in fixed-size groups (pairs, triples, k-groups), the pattern is: use a prev pointer before the group, perform the pointer surgery, then advance prev past the rearranged group. A dummy node at the front unifies the first group with all others.

03

Approach

1

Set up a dummy node before the head

Create a dummy node with dummy.next = head. Initialize prev = dummy. The dummy absorbs the head-changing logic — after all swaps, the new head is dummy.next.

2

Swap each pair with three pointer reassignments

While prev.next and prev.next.next both exist, let first = prev.next and second = prev.next.next. Perform: (1) prev.next = second — the predecessor now points to the second node, (2) first.next = second.next — the first node skips over the second to point at the rest, (3) second.next = first — the second node now points back to the first. This completes the swap.

3

Advance `prev` past the swapped pair

After the swap, first is now the second node of the pair. Set prev = first and continue the loop. When fewer than two nodes remain, the loop ends. Return dummy.next. Time is O(n), space is O(1).

04

Solution

1class Solution:
2 def swapPairs(self, head):
3 dummy = ListNode(0)
4 dummy.next = head
5 prev = dummy
6 while prev.next and prev.next.next:
7 first = prev.next
8 second = prev.next.next
9 prev.next = second
10 first.next = second.next
11 second.next = first
12 prev = first
13 return dummy.next
05

Common pitfalls

Swapping values instead of nodes

✗ Wrong
first.val, second.val = second.val, first.val
✓ Right
prev.next = second
first.next = second.next
second.next = first

The problem explicitly requires swapping nodes, not values. Value swapping is O(1) and tempting, but it violates the constraint and would fail if nodes carry additional data.

Forgetting to advance prev to first after the swap

✗ Wrong
prev = second
✓ Right
prev = first

After the swap, first is the second node of the pair — it is the last node before the next pair. Advancing prev to second (which is now the first node) skips over first and connects the next swap to the wrong predecessor.

Not using a dummy node, causing the head to be lost

✗ Wrong
prev = head
first = head
second = head.next
✓ Right
dummy = ListNode(0)
dummy.next = head
prev = dummy

Without a dummy, swapping the first pair changes the head of the list. You would need a separate variable to track the new head and special-case the first iteration. The dummy eliminates this.

06

Edge cases

Empty list

prev.next is None, so the loop never runs. Return None.

Single node

prev.next.next is None, so no pair exists. The single node is returned unchanged.

Odd number of nodes

The last node has no partner. The loop condition prev.next and prev.next.next stops before it, leaving the last node in place.

07

Complexity

Time
O(n)
Space
O(1)
Single pass, constant extra space. Each pair is swapped in three pointer operations.