Skip to content
← All posts

Swap Nodes in Pairs: Pairwise Linked List Manipulation

6 min read
leetcodeproblemmediumlinked-lists

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.

before1234nullafter2143null
Each pair of adjacent nodes swaps position. 1 and 2 swap, then 3 and 4 swap.

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:

  1. first.next = second.next - first now skips over second and points to whatever comes after the pair
  2. second.next = first - second now points back to first
  3. prev.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.

d1234prevfirstsecond

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.

d2134prevfirstsecond

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.

d2143prev

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.

2143

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:

  1. Base case: If there are fewer than two nodes, return the head as-is.
  2. Identify the pair: first is the current head, second is the node after it.
  3. Recurse: Swap all remaining pairs starting from second.next. Attach the result to first.next.
  4. Swap: Point second.next to first, making second the new front of this pair.
  5. Return: second is 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

ApproachTimeSpace
Iterative (dummy head)O(n)O(1)
RecursiveO(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.next is null. Return null. Correct.
  • Single node. prev.next exists but prev.next.next is 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 produce 2 -> 1 -> 3. Then prev is at node 1, prev.next is 3, but prev.next.next is null. The loop stops. Node 3 stays in place. Correct.
  • Two nodes. The minimal case where a swap actually happens. 1 -> 2 becomes 2 -> 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