Skip to content
← All posts

Swapping Nodes in a Linked List: Two-Pointer Technique

5 min read
leetcodeproblemmediumlinked-liststwo-pointers

Given the head of a linked list and an integer k, you need to swap the values of the kth node from the beginning and the kth node from the end, then return the head of the list.

This is LeetCode 1721: Swapping Nodes in a Linked List, a medium-difficulty problem that tests your ability to use the two-pointer gap technique on linked lists. The challenge is that you cannot index into a linked list the way you would with an array, so finding the kth node from the end requires a bit of cleverness.

Before12345kth from startkth from endk=2swapAfter14325
With k=2, the 2nd node from the start (value 2) and the 2nd node from the end (value 4) swap their values. The list structure stays the same.

Why this problem matters

The two-pointer gap technique is one of the most useful patterns for linked list problems. The idea is simple: if you maintain a fixed gap of k nodes between two pointers, then when the leading pointer reaches the end, the trailing pointer is exactly k nodes from the end. This lets you locate the kth-from-end node in a single pass without knowing the list's length ahead of time.

You will see this same technique in problems like "Remove Nth Node From End of List" and "Reorder List." Mastering it here gives you a building block that transfers directly to those problems.

The key insight

The key insight is that you do not need to know the length of the list to find the kth node from the end. Instead, you create a gap of exactly k nodes between two pointers. When the front pointer reaches the last node, the back pointer sits on the kth node from the end.

Here is how the algorithm works:

  1. Move a pointer k steps from the head. This is the kth node from the beginning. Save it.
  2. Set a second pointer at the head.
  3. Move both pointers forward together until the first pointer reaches the last node.
  4. The second pointer is now at the kth node from the end. Save it.
  5. Swap the values of the two saved nodes.

The solution

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def swap_nodes(head: ListNode, k: int) -> ListNode:
    fast = head
    for _ in range(k - 1):
        fast = fast.next
    first = fast

    slow = head
    while fast.next:
        fast = fast.next
        slow = slow.next
    second = slow

    first.val, second.val = second.val, first.val
    return head

The first loop advances fast by k - 1 steps. After this loop, fast points to the kth node from the beginning. You save a reference to it as first.

Next, you place slow at the head and advance both fast and slow one step at a time. The gap between them stays constant at k - 1 nodes. When fast.next is None, fast is on the last node and slow is on the kth node from the end. You save slow as second.

Finally, you swap the values stored in first and second. Because you are only swapping values (not rearranging pointers), the list structure remains unchanged. This is a one-line operation in Python.

Swapping values is simpler than swapping the actual nodes. If you were asked to swap the nodes themselves, you would need to track each node's predecessor and carefully rewire four pointers. Value swapping avoids all of that complexity. Unless the problem explicitly forbids modifying node values, prefer this approach.

Visual walkthrough

Let's trace through the algorithm on the list [1, 2, 3, 4, 5] with k = 2. Watch as the fast pointer (indigo) establishes the gap and the slow pointer (amber) rides it to the target node.

Step 1: Move fast pointer k=2 steps from head

12345fastfirst

Advance fast from head by k-1 = 1 step. fast lands on node with value 2. Save this as "first" (the kth node from the beginning).

Step 2: Set slow at head, advance both pointers

12345fastslowfirst

Place slow at the head. Move both fast and slow forward one step. fast is at value 3, slow is at value 2. The gap between them is k=2 nodes.

Step 3: Continue advancing both pointers

12345fastslowfirst

Both pointers move one more step. fast is at value 4, slow is at value 3. The gap stays constant.

Step 4: fast reaches the last node, slow is kth from end

12345fastslowfirstsecond

fast reached the last node (value 5). slow is at value 4, which is the kth node from the end. Save this as "second".

Step 5: Swap the values of first and second

14325firstsecond

Swap first.val (2) with second.val (4). The list is now [1, 4, 3, 2, 5]. Done!

Once both target nodes are identified, the swap is a single operation. The list goes from [1, 2, 3, 4, 5] to [1, 4, 3, 2, 5] without any pointer rewiring.

Complexity analysis

ApproachTimeSpace
Two-pointer value swapO(n)O(1)

Time: The algorithm makes one pass through the list. The first loop takes k steps, and the second loop takes n - k steps, for a total of n steps. This gives O(n) time.

Space: You only use a constant number of pointer variables (fast, slow, first, second). No extra data structures are needed, so space is O(1).

The building blocks

1. The k-gap two-pointer technique

# Create a gap of exactly k nodes between fast and slow
fast = head
for _ in range(k - 1):
    fast = fast.next

slow = head
while fast.next:
    fast = fast.next
    slow = slow.next
# slow is now k nodes from the end

This is the core pattern. By advancing fast first and then moving both pointers in lockstep, you guarantee that when fast hits the end, slow is exactly where you need it. The gap acts like a measuring stick that you slide along the list.

2. Finding the kth node from the end

def kth_from_end(head: ListNode, k: int) -> ListNode:
    fast = head
    for _ in range(k):
        fast = fast.next
    slow = head
    while fast:
        fast = fast.next
        slow = slow.next
    return slow

This is a slight variation where fast advances k steps (not k - 1) and the loop runs until fast is None (not until fast.next is None). The difference is subtle but important. In the swapping problem, you stop when fast is on the last node because you also need fast to identify the kth-from-start node. In this standalone version, you advance one extra step so that slow lands on the correct node when fast falls off the end.

Edge cases

  • k = 1: swapping head with tail
  • k = n: same as above but from the other direction
  • k points to the middle in odd-length list: swapping with itself (no change)
  • Two-node list: swap the only two nodes
  • Single node: k must be 1, swap with itself

From understanding to recall

The two-pointer gap technique is one of those patterns that feels obvious once you see it but is easy to fumble under pressure. Do you advance k steps or k - 1? Do you check fast.next or fast? These small details matter, and the only way to make them automatic is repeated practice at spaced intervals.

Build the muscle memory by coding this solution from scratch a few times over the next couple of weeks. Once the gap technique is second nature, you will recognize it instantly in other linked list problems.

Related posts

If you want a structured way to drill problems like this until they stick, CodeBricks uses spaced repetition to surface the right problem at the right time. Each session reinforces the patterns you have learned and exposes the gaps before they show up in an interview.