name: LinkedList In-Place Reversal
slug: linkedlist-reversal
difficulty_level: 2
pattern_type: technique
display_order: 14

description: >
  Reverse linked list nodes in-place by manipulating pointers without allocating
  extra space. This technique uses three pointers to track the previous, current,
  and next nodes while systematically reversing the direction of links.

when_to_use: |
  - Reversing an entire linked list
  - Reversing a portion of a linked list
  - Reversing in groups of K nodes
  - Palindrome linked list verification
  - Reordering list problems

metaphor: |
  Imagine a conga line where everyone faces forward. To reverse it, you don't
  rearrange people—you have each person turn around and grab the shoulders of
  whoever was behind them. You process one person at a time: they turn around,
  the next person steps forward, and so on until everyone faces the opposite direction.

  Another analogy: reversing a chain of paper clips. You unclip each one from its
  forward neighbor and clip it to its backward neighbor, working through the chain.

core_concept: |
  Linked list reversal uses **three pointers** moving through the list:

  - **prev**: Points to the already-reversed portion (starts as null)
  - **curr**: The node currently being processed
  - **next**: Temporarily stores the next node before we break the link

  At each step:
  1. Save `curr.next` in `next` (before we lose it)
  2. Reverse the link: `curr.next = prev`
  3. Advance: `prev = curr`, `curr = next`

  The key insight is that we're not moving nodes—we're redirecting pointers.
  This achieves O(n) time with O(1) space.

  For **partial reversal** (reversing between positions m and n), we:
  1. Navigate to position m-1 (the node before reversal starts)
  2. Reverse nodes from m to n
  3. Reconnect the reversed portion to the rest of the list

visualization: |
  **Full list reversal:**

  ```
  Initial: 1 → 2 → 3 → 4 → null
           prev=null, curr=1

  Step 1: Save next=2, reverse 1's link
          null ← 1   2 → 3 → 4
                prev curr

  Step 2: Save next=3, reverse 2's link
          null ← 1 ← 2   3 → 4
                    prev curr

  Step 3: Save next=4, reverse 3's link
          null ← 1 ← 2 ← 3   4
                        prev curr

  Step 4: Save next=null, reverse 4's link
          null ← 1 ← 2 ← 3 ← 4
                            prev curr=null

  Result: 4 → 3 → 2 → 1 → null
  ```

  **Partial reversal (positions 2 to 4):**

  ```
  Initial: 1 → 2 → 3 → 4 → 5
           positions: 1   2   3   4   5

  Goal: 1 → 4 → 3 → 2 → 5

  Step 1: Find node before position 2
          before = node 1

  Step 2: Reverse nodes 2, 3, 4
          1   null ← 2 ← 3 ← 4   5
          ↑                  ↑   ↑
       before             prev  curr

  Step 3: Reconnect
          before.next.next = curr (2 → 5)
          before.next = prev (1 → 4)

  Result: 1 → 4 → 3 → 2 → 5
  ```

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


  def reverse_list(head: ListNode) -> ListNode:
      """Reverse entire linked list."""
      prev = None
      curr = head

      while curr:
          next_node = curr.next  # Save next
          curr.next = prev       # Reverse link
          prev = curr            # Advance prev
          curr = next_node       # Advance curr

      return prev  # New head


  def reverse_between(head: ListNode, m: int, n: int) -> ListNode:
      """Reverse nodes from position m to n (1-indexed)."""
      if not head or m == n:
          return head

      dummy = ListNode(0)
      dummy.next = head
      before = dummy

      # Move to node before reversal starts
      for _ in range(m - 1):
          before = before.next

      # Reverse n - m + 1 nodes
      prev = None
      curr = before.next
      for _ in range(n - m + 1):
          next_node = curr.next
          curr.next = prev
          prev = curr
          curr = next_node

      # Reconnect
      before.next.next = curr  # tail of reversed → rest of list
      before.next = prev       # before → new head of reversed

      return dummy.next


  def reverse_k_group(head: ListNode, k: int) -> ListNode:
      """Reverse nodes in groups of k."""
      # Count total nodes
      count = 0
      node = head
      while node:
          count += 1
          node = node.next

      dummy = ListNode(0)
      dummy.next = head
      before = dummy

      while count >= k:
          # Reverse k nodes
          prev = None
          curr = before.next
          for _ in range(k):
              next_node = curr.next
              curr.next = prev
              prev = curr
              curr = next_node

          # Reconnect
          tail = before.next
          tail.next = curr
          before.next = prev

          # Move to next group
          before = tail
          count -= k

      return dummy.next


  def reverse_list_recursive(head: ListNode) -> ListNode:
      """Reverse list using recursion."""
      if not head or not head.next:
          return head

      new_head = reverse_list_recursive(head.next)
      head.next.next = head  # Reverse link
      head.next = None       # Prevent cycle

      return new_head

recognition_signals:
  - "reverse linked list"
  - "reverse between"
  - "reverse in groups"
  - "reverse k-group"
  - "palindrome linked list"
  - "reorder list"
  - "swap nodes"
  - "rotate list"

common_mistakes:
  - title: Losing reference to next node
    description: |
      Reversing `curr.next` before saving it means you can't advance to the
      next node.
    fix: |
      Always save the next node first:
      ```python
      next_node = curr.next  # Save FIRST
      curr.next = prev       # Then reverse
      ```

  - title: Forgetting to update connections in partial reversal
    description: |
      Reversing the middle portion without reconnecting it to the beginning
      and end of the list breaks the list.
    fix: |
      After reversing, reconnect both ends:
      ```python
      before.next.next = curr  # tail → rest
      before.next = prev       # before → new head
      ```

  - title: Not using a dummy node
    description: |
      When the reversal might include the head, handling the head separately
      adds complexity and edge cases.
    fix: |
      Use a dummy node pointing to head. This simplifies edge cases:
      ```python
      dummy = ListNode(0)
      dummy.next = head
      # ... reversal logic ...
      return dummy.next
      ```

  - title: Off-by-one with positions
    description: |
      Confusing 0-indexed vs 1-indexed positions causes reversal of wrong nodes.
    fix: |
      Clarify indexing convention. For 1-indexed positions, loop `m-1` times
      to reach the node *before* position m.

variations:
  - name: Full reversal
    description: |
      Reverse the entire linked list. Simplest form—just walk through and
      reverse each link.
    example: "Reverse Linked List"

  - name: Partial reversal
    description: |
      Reverse only nodes between positions m and n. Need to track connection
      points before and after the reversed section.
    example: "Reverse Linked List II"

  - name: K-group reversal
    description: |
      Reverse every k consecutive nodes. Often requires counting total nodes
      first to know when to stop.
    example: "Reverse Nodes in k-Group"

  - name: Alternating reversal
    description: |
      Reverse every other group of k nodes. Combines k-group logic with
      skip logic.
    example: "Reverse Alternate K Nodes"

  - name: Recursive reversal
    description: |
      Elegant recursive solution that reverses by relying on the recursive
      call to reverse the rest, then fixing up the current node.
    example: "Reverse Linked List (recursive approach)"

related_patterns:
  - fast-slow-pointers
  - two-pointers

prerequisite_patterns: []

visualization_examples:
  - id: reverse-linked-list
    title: Reverse Entire Linked List
    input:
      list: [1, 2, 3, 4]
    code: |
      def reverse_list(head):
          prev = None
          curr = head

          while curr:
              next_node = curr.next
              curr.next = prev
              prev = curr
              curr = next_node

          return prev
    steps:
      - id: step-1
        description: "Initialize prev=None, curr=head (node 1)."
        structures:
          list:
            type: linkedlist
            nodes:
              - { value: 1, state: active }
              - { value: 2, state: default }
              - { value: 3, state: default }
              - { value: 4, state: default }
            pointers:
              curr: 0
        variables:
          prev: "null"
        codeHighlight:
          startLine: 2
          endLine: 3

      - id: step-2
        description: "Save next=2, reverse link: 1→null. Move pointers forward."
        structures:
          list:
            type: linkedlist
            nodes:
              - { value: 1, state: visited, annotations: ["→null"] }
              - { value: 2, state: active }
              - { value: 3, state: default }
              - { value: 4, state: default }
            pointers:
              prev: 0
              curr: 1
        variables:
          next_node: 2
        codeHighlight:
          startLine: 6
          endLine: 9

      - id: step-3
        description: "Save next=3, reverse link: 2→1. Move pointers forward."
        structures:
          list:
            type: linkedlist
            nodes:
              - { value: 1, state: visited, annotations: ["→null"] }
              - { value: 2, state: visited, annotations: ["→1"] }
              - { value: 3, state: active }
              - { value: 4, state: default }
            pointers:
              prev: 1
              curr: 2
        variables:
          next_node: 3
        codeHighlight:
          startLine: 6
          endLine: 9

      - id: step-4
        description: "Save next=4, reverse link: 3→2. Move pointers forward."
        structures:
          list:
            type: linkedlist
            nodes:
              - { value: 1, state: visited, annotations: ["→null"] }
              - { value: 2, state: visited, annotations: ["→1"] }
              - { value: 3, state: visited, annotations: ["→2"] }
              - { value: 4, state: active }
            pointers:
              prev: 2
              curr: 3
        variables:
          next_node: 4
        codeHighlight:
          startLine: 6
          endLine: 9

      - id: step-5
        description: "Save next=null, reverse link: 4→3. curr becomes null, loop ends."
        structures:
          list:
            type: linkedlist
            nodes:
              - { value: 1, state: visited, annotations: ["→null"] }
              - { value: 2, state: visited, annotations: ["→1"] }
              - { value: 3, state: visited, annotations: ["→2"] }
              - { value: 4, state: found, annotations: ["→3", "new head"] }
            pointers:
              prev: 3
        variables:
          next_node: "null"
        codeHighlight:
          startLine: 11
          endLine: 11

      - id: step-6
        description: "Return prev (node 4). Reversed list: 4→3→2→1→null"
        structures:
          reversed:
            type: linkedlist
            nodes:
              - { value: 4, state: found, annotations: ["head"] }
              - { value: 3, state: default }
              - { value: 2, state: default }
              - { value: 1, state: default }
        variables:
          result: "4→3→2→1→null"
        codeHighlight:
          startLine: 11
          endLine: 11
