Loading problems...
TL;DR: To solve this problem efficiently in one pass, use a dummy node to handle edge cases and iteratively move the node following the current "head" of the sub-segment to the front of the sub-segment.
The LeetCode 92 problem, "Reverse Linked List II," asks us to reverse a specific portion of a singly linked list. We are given the head of the list and two integers, left and right. Our task is to reverse the nodes located between position left and position right (inclusive) while keeping the rest of the list intact. The indices are 1-based.
This is a popular interview question because it tests pointer manipulation skills more rigorously than a standard full-list reversal. It requires careful handling of the connections between the reversed sublist and the unmodified parts of the list.
A naive or brute force approach typically involves breaking the problem down into three explicit phases: extraction, reversal, and reconnection.
left.left to right, storing these node values (or the nodes themselves) in a temporary data structure like an array or vector.Pseudo-code:
textfunction reverseBetween(head, left, right): nodes = [] current = head position = 1 // Collect nodes in the range while current: if position >= left and position <= right: nodes.push(current.val) current = current.next position++ // Reverse the collected values reverse(nodes) // Write values back current = head position = 1 index = 0 while current: if position >= left and position <= right: current.val = nodes[index] index++ current = current.next position++ return head
Complexity Analysis:
Why it fails: While this solution might pass within the time limits for , it fails the spirit of the problem. The follow-up explicitly asks for a one-pass solution using extra space. In an interview context, allocating an array to solve a linked list pointer problem is generally considered suboptimal because it bypasses the core challenge of pointer manipulation.
The key intuition for the optimal solution is to treat the sublist reversal as a sequence of "move to front" operations. Instead of reversing the pointers all at once or swapping values, we maintain a fixed reference to the node immediately before the sub-segment (let's call this prev) and the first node of the sub-segment (let's call this curr).
During the reversal process within the range [left, right], the curr node remains the same (it eventually becomes the tail of the reversed sublist). We iteratively take the node immediately following curr (let's call it next_node) and move it to the position right after prev.
The Invariant:
At any step inside the loop, the sub-segment from left to left + k is reversed. We repeat this operation right - left times.
Visual Description:
Imagine the list segment: A -> [B -> C -> D] -> E where we want to reverse B through D.
prev points to A, curr points to B. next_node is C.A -> C -> B -> D -> Ecurr is still B. next_node becomes D. We detach D and insert it between A and C.
A -> D -> C -> B -> EBy consistently moving the "next" node to the front of the sub-segment, we reverse the list in place with a single pass through the relevant nodes.

Let's trace the algorithm with head = [1, 2, 3, 4, 5], left = 2, right = 4.
dummy node with value 0. dummy.next points to 1.prev starts at dummy.prev:
prev forward left - 1 (1) time.prev now points to node 1.curr points to prev.next (node 2).right - left (4 - 2 = 2) reversal operations.next_node is curr.next (node 3).curr.next = next_node.next (Node 2 points to 4).next_node.next = prev.next (Node 3 points to 2).prev.next = next_node (Node 1 points to 3).1 -> 3 -> 2 -> 4 -> 5curr is still node 2. next_node is now curr.next (node 4).curr.next = next_node.next (Node 2 points to 5).next_node.next = prev.next (Node 4 points to 3).prev.next = next_node (Node 1 points to 4).1 -> 4 -> 3 -> 2 -> 5dummy.next (node 1).[1, 4, 3, 2, 5].The correctness relies on the invariant that prev always points to the node immediately preceding the reversal group. The curr pointer acts as the anchor for the original start of the group.
In every iteration, we take the node curr.next and insert it between prev and prev.next. This effectively reverses the order of nodes processed so far relative to the prev node.
left to right, the pointers outside this range are never touched, preserving the rest of the list structure.left=1, prev is the dummy, and insertions happen at the true head of the list, correctly updating the head reference.cpp/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* reverseBetween(ListNode* head, int left, int right) { if (!head || left == right) return head; ListNode dummy(0); dummy.next = head; ListNode* prev = &dummy; // Step 1: Move prev to the node just before the 'left' position for (int i = 0; i < left - 1; ++i) { prev = prev->next; } // Step 2: Reverse the sublist // curr: the first node of the sublist to be reversed ListNode* curr = prev->next; for (int i = 0; i < right - left; ++i) { ListNode* next_node = curr->next; // Rewire pointers curr->next = next_node->next; next_node->next = prev->next; prev->next = next_node; } return dummy.next; } };
java/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode reverseBetween(ListNode head, int left, int right) { if (head == null || left == right) return head; // Dummy node to handle edge case where left = 1 ListNode dummy = new ListNode(0); dummy.next = head; // Step 1: Reach the node just before the sublist ListNode prev = dummy; for (int i = 0; i < left - 1; i++) { prev = prev.next; } // Step 2: Reverse the sublist ListNode curr = prev.next; for (int i = 0; i < right - left; i++) { ListNode nextNode = curr.next; // Pointer manipulation curr.next = nextNode.next; nextNode.next = prev.next; prev.next = nextNode; } return dummy.next; } }
python# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]: if not head or left == right: return head # Dummy node simplifies edge cases where head is modified dummy = ListNode(0, head) prev = dummy # Step 1: Move prev to position left - 1 for _ in range(left - 1): prev = prev.next # Step 2: Reverse the sublist curr = prev.next for _ in range(right - left): next_node = curr.next # Pointer manipulation curr.next = next_node.next next_node.next = prev.next prev.next = next_node return dummy.next
left index, and then perform right - left constant-time pointer operations. In the worst case (left=1, right=N), we visit every node exactly once.dummy, prev, curr, next_node) regardless of the size of the input list.The Linked List - In-place Reversal pattern is highly reusable. Mastering the pointer rewiring logic in LeetCode 92 allows you to solve several other hard problems:
next pointers while traversing.left=1 and right=N.k.left = 1?
left = 1, the head of the list changes. Without a dummy node, you have to write separate logic to handle the new head. The dummy node unifies the logic by ensuring there is always a prev node.right times or right - left + 1 times.right - left times. If there are 3 nodes in the range, we perform 2 swaps to reverse them.currcurr points to the original first node of the sublist. It should not move forward; instead, the node after it (next_node) is the one being moved. If you move curr, you lose track of the tail of the reversed segment.