Skip to content

Swap Operations

Swapping nodes and pairs in linked lists


Overview

Swap operations involve exchanging positions of nodes in a linked list. These problems test your ability to carefully manipulate multiple pointers while maintaining list integrity.

Swap Operations Visualization


Swap Nodes in Pairs (LeetCode #24)

Problem Statement

Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list's nodes.

Iterative Solution

python
def swapPairs(head: ListNode) -> ListNode:
    """
    Swap every two adjacent nodes.
    Time: O(n), Space: O(1)
    """
    dummy = ListNode(0)
    dummy.next = head
    prev = dummy

    while prev.next and prev.next.next:
        # Nodes to swap
        first = prev.next
        second = prev.next.next

        # Perform swap
        prev.next = second
        first.next = second.next
        second.next = first

        # Move prev forward
        prev = first

    return dummy.next
java
public ListNode swapPairs(ListNode head) {
    ListNode dummy = new ListNode(0);
    dummy.next = head;
    ListNode prev = dummy;

    while (prev.next != null && prev.next.next != null) {
        ListNode first = prev.next;
        ListNode second = prev.next.next;

        prev.next = second;
        first.next = second.next;
        second.next = first;

        prev = first;
    }

    return dummy.next;
}

Complexity: Time O(n) · Space O(1)

  • Time: O(n) because we traverse the list once, processing each pair of nodes
  • Space: O(1) because we only use pointers (dummy, prev, first, second) regardless of list size

Recursive Solution

python
def swapPairs_recursive(head: ListNode) -> ListNode:
    """
    Recursive approach - swap first pair, recurse on rest.
    Time: O(n), Space: O(n) for recursion stack
    """
    # Base case: 0 or 1 nodes
    if not head or not head.next:
        return head

    # Nodes to swap
    first = head
    second = head.next

    # Swap and recurse
    first.next = swapPairs_recursive(second.next)
    second.next = first

    return second  # Second is new head of this pair

Complexity: Time O(n) · Space O(n)

  • Time: O(n) because each node is visited exactly once during recursive calls
  • Space: O(n) because the recursion stack grows to n/2 frames (one per pair)

Visual Example

Before: 1 -> 2 -> 3 -> 4

Step 1: Swap (1,2)
- prev = dummy, first = 1, second = 2
- dummy -> 2 -> 1 -> 3 -> 4
- prev = 1

Step 2: Swap (3,4)
- prev = 1, first = 3, second = 4
- 1 -> 4 -> 3
- prev = 3

After: 2 -> 1 -> 4 -> 3

Swap Kth Node from Beginning and End (LeetCode #1721)

Problem Statement

Given a linked list, swap the kth node from the beginning with the kth node from the end. Return the head of the linked list after swapping.

Solution

python
def swapNodes(head: ListNode, k: int) -> ListNode:
    """
    Swap kth from start with kth from end.
    Time: O(n), Space: O(1)
    """
    # Find kth from beginning
    first = head
    for _ in range(k - 1):
        first = first.next

    # Find kth from end using two pointers
    second = head
    temp = first
    while temp.next:
        second = second.next
        temp = temp.next

    # Swap values (simple approach)
    first.val, second.val = second.val, first.val

    return head
java
public ListNode swapNodes(ListNode head, int k) {
    ListNode first = head;
    for (int i = 0; i < k - 1; i++) {
        first = first.next;
    }

    ListNode second = head, temp = first;
    while (temp.next != null) {
        second = second.next;
        temp = temp.next;
    }

    int tmp = first.val;
    first.val = second.val;
    second.val = tmp;

    return head;
}

Complexity: Time O(n) · Space O(1)

  • Time: O(n) because we traverse to find kth from start, then use two pointers to find kth from end
  • Space: O(1) because we only swap values, using a constant number of pointers

Swap by Rearranging Pointers (More Complex)

python
def swapNodes_pointers(head: ListNode, k: int) -> ListNode:
    """
    Swap by actually rearranging pointers (harder).
    Handles edge cases like adjacent nodes, same node.
    """
    if not head or not head.next:
        return head

    dummy = ListNode(0)
    dummy.next = head

    # Find kth from beginning and its previous
    prev1 = dummy
    for _ in range(k - 1):
        prev1 = prev1.next
    first = prev1.next

    # Find kth from end and its previous
    prev2 = dummy
    temp = dummy
    for _ in range(k):
        temp = temp.next
    while temp.next:
        prev2 = prev2.next
        temp = temp.next
    second = prev2.next

    # Handle same node case
    if first == second:
        return head

    # Handle adjacent nodes
    if first.next == second:
        prev1.next = second
        first.next = second.next
        second.next = first
    elif second.next == first:
        prev2.next = first
        second.next = first.next
        first.next = second
    else:
        # Non-adjacent swap
        prev1.next = second
        prev2.next = first
        first.next, second.next = second.next, first.next

    return dummy.next

Complexity: Time O(n) · Space O(1)

  • Time: O(n) because we traverse to find both nodes and their predecessors
  • Space: O(1) because we only use pointers to rearrange nodes without additional data structures

Swap Two Specific Nodes by Value

Problem Statement

Swap nodes with values x and y.

python
def swapNodesByValue(head: ListNode, x: int, y: int) -> ListNode:
    """
    Swap nodes with values x and y.
    """
    if x == y:
        return head

    dummy = ListNode(0)
    dummy.next = head

    # Find node x and its prev
    prev_x, node_x = None, None
    prev = dummy
    curr = head
    while curr:
        if curr.val == x:
            prev_x, node_x = prev, curr
            break
        prev = curr
        curr = curr.next

    # Find node y and its prev
    prev_y, node_y = None, None
    prev = dummy
    curr = head
    while curr:
        if curr.val == y:
            prev_y, node_y = prev, curr
            break
        prev = curr
        curr = curr.next

    # If either not found
    if not node_x or not node_y:
        return head

    # Swap
    prev_x.next = node_y
    prev_y.next = node_x
    node_x.next, node_y.next = node_y.next, node_x.next

    return dummy.next

Complexity: Time O(n) · Space O(1)

  • Time: O(n) because we traverse the list twice to find both nodes x and y
  • Space: O(1) because we only use pointers to track positions and rearrange nodes

Reverse and Swap Alternating Pairs

Problem Statement

For each pair of nodes, reverse the first and keep the second as is.

python
def reverseAlternatePairs(head: ListNode) -> ListNode:
    """
    Reverse first pair, keep second pair, alternate.
    1->2->3->4->5->6 becomes 2->1->3->4->6->5
    """
    dummy = ListNode(0)
    dummy.next = head
    prev = dummy
    reverse = True

    while prev.next and prev.next.next:
        first = prev.next
        second = prev.next.next

        if reverse:
            # Swap this pair
            prev.next = second
            first.next = second.next
            second.next = first
            prev = first
        else:
            # Keep this pair
            prev = second

        reverse = not reverse

    return dummy.next

Complexity: Time O(n) · Space O(1)

  • Time: O(n) because we traverse the list once, alternately swapping and skipping pairs
  • Space: O(1) because we only use pointers regardless of list size

Swap Every K Nodes (Partial)

Problem Statement

Swap first k nodes with last k nodes.

python
def swapFirstAndLastK(head: ListNode, k: int) -> ListNode:
    """
    Swap first k nodes with last k nodes.
    """
    if not head:
        return head

    # Get length
    length = 0
    curr = head
    while curr:
        length += 1
        curr = curr.next

    if 2 * k > length:
        return head  # Overlapping sections

    # Collect first k and last k node references
    first_k = []
    last_k = []

    curr = head
    for i in range(length):
        if i < k:
            first_k.append(curr)
        if i >= length - k:
            last_k.append(curr)
        curr = curr.next

    # Swap values
    for i in range(k):
        first_k[i].val, last_k[i].val = last_k[i].val, first_k[i].val

    return head

Complexity: Time O(n) · Space O(k)

  • Time: O(n) because we traverse the list once, collecting first k and last k nodes
  • Space: O(k) for storing references to the first k and last k nodes

Common Patterns

Adjacent Pair Swap Pattern

python
dummy = ListNode(0)
dummy.next = head
prev = dummy

while prev.next and prev.next.next:
    first = prev.next
    second = prev.next.next

    # Swap
    prev.next = second
    first.next = second.next
    second.next = first

    prev = first  # Move to end of swapped pair

return dummy.next

Two-Pointer for Kth from End

python
# Find kth from end
slow = fast = head
for _ in range(k):
    fast = fast.next
while fast:
    slow = slow.next
    fast = fast.next
# slow is now kth from end

Edge Cases

  1. Empty list: Return None
  2. Single node: Return as-is (no pair to swap)
  3. Odd number of nodes: Last node stays in place
  4. k larger than list: Handle gracefully
  5. Swapping same node: No change needed
  6. Adjacent nodes: Special pointer handling

Complexity Summary

ProblemTimeSpace
Swap Pairs (iterative)O(n)O(1)
Swap Pairs (recursive)O(n)O(n)
Swap Kth from Start/EndO(n)O(1)
Swap by ValueO(n)O(1)

Swap Nodes in Pairs (LeetCode 24)

Problem: Given a linked list, swap every two adjacent nodes and return its head without modifying node values.

Key Insight: Use a dummy node to handle head changes, and track pairs with prev/first/second pointers.

Approach: For each pair, redirect pointers: prev -> second -> first -> next_pair. Move prev to first (new end of swapped pair).

Complexity: Time O(n), Space O(1) iterative / O(n) recursive

Swapping Nodes in a Linked List (LeetCode 1721)

Problem: Swap the values of the kth node from the beginning and the kth node from the end (1-indexed).

Key Insight: Use two-pointer technique to find kth from end - advance fast pointer k steps, then move both until fast reaches end.

Approach: Find kth from start, then use two pointers to find kth from end. Swap values (simplest) or rearrange pointers (harder).

Complexity: Time O(n), Space O(1)

Reverse Nodes in K-Group (LeetCode 25)

Problem: Reverse nodes k at a time in a linked list. If remaining nodes < k, leave them as-is.

Key Insight: Count k nodes first, then reverse that segment, and recursively/iteratively handle remaining list.

Approach: For each group: verify k nodes exist, reverse them in place, connect reversed segment to rest of list.

Complexity: Time O(n), Space O(1) iterative / O(n/k) recursive

Reverse Linked List II (LeetCode 92)

Problem: Reverse nodes from position left to position right in a singly linked list.

Key Insight: Use dummy node to handle edge case when left=1, track node before reversal segment.

Approach: Navigate to position left-1, reverse nodes from left to right using standard reversal, reconnect segments.

Complexity: Time O(n), Space O(1)


Interview Tips

  1. Use dummy node: When head might change
  2. Draw the pointers: Before and after each swap
  3. Handle edge cases: Single node, adjacent nodes
  4. Swap values vs nodes: Clarify what's expected
  5. Test odd length: Last node handling

Sources