Reverse Linked List II — In-Place Partial Reversal Explained

Sanjeev SharmaSanjeev Sharma
8 min read

Advertisement

Problem Statement

LeetCode 92 — Reverse Linked List II Difficulty: Medium | Pattern: Partial In-Place Reversal

Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list. The list is 1-indexed.

Constraints:

  • Number of nodes: 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n

Example 1:

Input:  head = [1, 2, 3, 4, 5], left = 2, right = 4
Output: [1, 4, 3, 2, 5]

Example 2:

Input:  head = [5], left = 1, right = 1
Output: [5]

Example 3:

Input:  head = [3, 5], left = 1, right = 2
Output: [5, 3]

Why This Problem Matters

Reverse Linked List II is one of the most instructive pointer manipulation problems in the entire LeetCode catalog. Facebook, Microsoft, and Amazon ask it in phone screens and onsite interviews because it tests not just whether you understand reversal, but whether you can precisely manage multi-pointer state while reversing only a subrange — leaving the rest of the list intact.

The full reversal (LC 206) is taught as a warm-up exercise. The partial reversal forces you to think carefully about how to reconnect the reversed segment to the unmodified head and tail of the list. Getting this wrong — even by one pointer assignment — produces incorrect output that is difficult to debug without drawing the state.

In practice, partial list reversal appears in network routing algorithms, undo buffers, and text editor data structures (rope structures). Any time you need to rearrange a contiguous segment of a sequence in-place, this is the template.

The elegant one-pass solution uses a technique called "front insertion" — moving nodes one by one to the front of the segment being reversed, without needing separate arrays or multiple traversals. This is a key pattern that also appears in the "Reverse Nodes in k-Group" problem (LC 25).

The Core Insight

The key insight is front insertion reversal: instead of reversing the segment and then reconnecting, you maintain a fixed prev pointer (the node before the reversal zone) and repeatedly move the first node of the remaining segment to become the new head of the reversed portion.

Concretely:

  1. Advance prev to the node just before position left. This is the anchor.
  2. Let curr be the first node in the reversal zone (prev.next).
  3. Repeat right - left times: move curr.next to the front of the reversed segment by inserting it after prev.

This elegant trick avoids the need to track the "end" of the reversed segment separately — curr naturally falls to the tail of the reversed zone after all insertions.

Using a dummy head node eliminates the edge case where left = 1 (reversal starts at the head).

Visual Dry Run

Input: [1, 2, 3, 4, 5], left=2, right=4

Initial: dummy -> 1 -> [2 -> 3 -> 4] -> 5
         prev = node(1), curr = node(2)

Iteration 1 (move node(3) after prev):

nxt = curr.next = node(3)
curr.next = nxt.next = node(4)
nxt.next = prev.next = node(2)
prev.next = nxt = node(3)
 
State: dummy -> 1 -> 3 -> 2 -> 4 -> 5

Iteration 2 (move node(4) after prev):

nxt = curr.next = node(4)
curr.next = nxt.next = node(5)
nxt.next = prev.next = node(3)
prev.next = nxt = node(4)
 
State: dummy -> 1 -> 4 -> 3 -> 2 -> 5

Done — 2 iterations for right - left = 4 - 2 = 2.

Solution (Optimal)

from typing import Optional
 
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
 
def reverseBetween(head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
    dummy = ListNode(0)
    dummy.next = head
    prev = dummy
 
    # Step 1: Advance prev to node just before position 'left'
    for _ in range(left - 1):
        prev = prev.next
 
    # Step 2: Front insertion — repeat (right - left) times
    curr = prev.next
    for _ in range(right - left):
        nxt = curr.next          # node to move
        curr.next = nxt.next     # remove nxt from its position
        nxt.next = prev.next     # nxt points to current front of reversed segment
        prev.next = nxt          # nxt becomes new front of reversed segment
 
    return dummy.next
function reverseBetween(head, left, right) {
    const dummy = { val: 0, next: head };
    let prev = dummy;
 
    // Step 1: Advance prev to node before position 'left'
    for (let i = 0; i < left - 1; i++) {
        prev = prev.next;
    }
 
    // Step 2: Front insertion reversal
    let curr = prev.next;
    for (let i = 0; i < right - left; i++) {
        const nxt = curr.next;
        curr.next = nxt.next;
        nxt.next = prev.next;
        prev.next = nxt;
    }
 
    return dummy.next;
}

Complexity:

MetricValue
TimeO(n) — single pass
SpaceO(1) — in-place, no extra data structures

Common Mistakes

  1. Not using a dummy head: Without a dummy, the case where left = 1 requires special handling to update the head pointer. Always use a dummy to make the code uniform.
  2. Off-by-one in initial advance: The loop to advance prev should run left - 1 times (not left). After the loop, prev should be at position left - 1.
  3. Wrong number of front insertions: The front insertion loop runs right - left times (not right - left + 1). The first node of the zone (curr) is already in its "reversed" position; you only need to move right - left more nodes.
  4. Incorrect pointer order in front insertion: The four pointer assignments must happen in this exact order: capture nxt, update curr.next, update nxt.next, update prev.next. Changing the order corrupts the list.
  5. Testing only on normal cases: Always test with left = 1 (reversal includes the head), left = right (single-node range, no-op), and right = n (reversal includes the tail).

Interview Tips

  • Draw the before/after state: Show the list before reversal and what it should look like after. This demonstrates you understand the problem before writing code.
  • Explain the front insertion technique: "Instead of reversing the segment first and reconnecting, I move nodes one at a time to the front of the reversed portion. This handles everything in one pass."
  • Name the invariant: "After each iteration, the segment from prev.next to curr is reversed. curr always points to the node that will next enter the reversal zone."
  • Walk through the pointer assignments: Do not just write the four lines — verbalize each one. This is where candidates lose points when they have an order bug.
  • Offer the two-pass alternative: Mention that you could reverse the segment separately and then reconnect, but it requires tracking more pointers and is more error-prone.

Follow-up Questions

  1. LeetCode 25 — Reverse Nodes in k-Group: Applies the same front insertion technique to groups of k nodes repeatedly.
  2. What if you needed to reverse multiple non-overlapping ranges? Apply the same algorithm once per range, using the returned head of each operation.
  3. Can you do it recursively? Yes, though recursion adds O(n) stack space. Discuss the tradeoff.
  4. What if left = right? Zero front insertions are performed — the list is unchanged. The algorithm handles this correctly.
  5. Reverse the entire list using this method: Set left=1 and right=n. Works perfectly with the dummy head approach.
  6. LeetCode 206 — Reverse Linked List: The simpler full-reversal version. Make sure you can solve both in the same interview.

Key Takeaways

  • Use a dummy head to eliminate the special case where the reversal starts at position 1.
  • The front insertion technique reverses the segment in one pass: repeatedly move curr.next to immediately after prev.
  • The initial advance loop runs left - 1 times; the reversal loop runs right - left times.
  • The four pointer assignments in each iteration must follow a strict order — capturing nxt first prevents losing the reference.
  • This pattern directly extends to LC 25 (Reverse Nodes in k-Group), one of the most frequently asked hard linked list problems.
  • Time is O(n) and space is O(1) — optimal for this problem and the expected answer in any FAANG interview.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro

Related reading