Question 1

Given the head of a singly linked list, swap every two nodes and return its head.

Approach

In the realm of linked lists, a classic algorithmic puzzle is to rearrange the structure by swapping adjacent pairs of nodes. Your task is to develop a solution that elegantly modifies the links within a given linked list to achieve this pairwise swap.

Pseudo Code

Code
function swapPairs(head)
  //  Handle base cases: empty list or single node
  if head == NULL or head.next == NULL
    return head

  // Create pointers to track nodes:
  // 'prev' will point to the node before the pair to swap  
  // 'curr' will point to the first node of the pair  
  // 'next' will point to the second node of the pair
  prev = NULL
  curr = head
  next = head.next

  // Iterate through the list:  
  while curr != NULL and next != NULL
      // Set prev.next to the second node, effectively reversing the first pair
      if prev != NULL 
          prev.next = next 
      else
          head = next // Update 'head' for the first pair swap

      // Perform the swap
      curr.next = next.next
      next.next = curr 

      // Move pointers to prepare for the next swap
      prev = curr
      curr = curr.next 
      next = curr.next if curr != NULL 

  return head
Explanation
  1. Base Cases: Check if the list is empty (head == NULL) or if it has only one node (head.next == NULL). In these cases, no swapping is needed, so you directly return the head.
  2. Pointers:
    • prev: Keeps track of the node before the current pair to update its next pointer.
    • curr: Points to the first node of the current pair to be swapped.
    • next: Points to the second node of the current pair.
  3. Iteration: The while loop iterates until you’ve processed all pairs.
  4. Reversing the Pair:
    • If prev is not NULL (it won’t be for the first pair), you set prev.next to next, effectively reversing the direction of the first two nodes.
    • If prev is NULL, this is the first pair in the list so you update the head pointer to next.
  5. Swapping:
    • curr.next is set to next.next (the node after the pair).
    • next.next is set to curr (completing the swap).
  6. Update Pointers:
    • Update prevcurr, and next to prepare for the next pair swap.

Implementation

Golang
package main

import "fmt"

// Node represents a node in the singly linked list
type Node struct {
    Val  int
    Next *Node
}

// Function to swap pairs in the linked list
func swapPairs(head *Node) *Node {
    // Base cases: empty list or single node
    if head == nil || head.Next == nil {
        return head
    }

    // Create dummy head (simplifies initial swap)
    dummy := &Node{Next: head}
    prev := dummy
    curr := head
    next := head.Next

    // Iterate and swap pairs
    for curr != nil && next != nil {
        // Reverse pair
        prev.Next = next
        curr.Next = next.Next
        next.Next = curr

        // Update pointers for the next iteration
        prev = curr
        curr = curr.Next
        if curr != nil { // Ensure 'next' isn't out of bounds
            next = curr.Next
        }
    }

    return dummy.Next // Return the new head (from the dummy node)
}

// Example usage
func main() {
    // Create a simple linked list
    head := &Node{Val: 1, Next: &Node{Val: 2, Next: &Node{Val: 3, Next: &Node{Val: 4}}}}

    // Swap pairs
    newHead := swapPairs(head)

    // Print the modified list
    for newHead != nil {
        fmt.Print(newHead.Val, " ")
        newHead = newHead.Next
    }
    fmt.Println()
}