Reverse Linked List II
Problem Description
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.
Examples
Example 1:Input: head = [1,2,3,4,5], left = 2, right = 4 Output: [1,4,3,2,5]
Input: head = [5], left = 1, right = 1 Output: [5]
Constraints
- The number of nodes in the list is
n. 1 <= n <= 500-500 <= Node.val <= 5001 <= left <= right <= n
Pointer Bookkeeping for Sub-reversal
To reverse a portion of the list in a single pass:
- Locate the Boundaries: Move a pointer
prevto the node immediately before theleftposition (indexleft - 1). The node atleftbecomes thetailof our reversed sub-segment. - Reverse the Sub-segment: We iterate
right - lefttimes. In each iteration, we pluck the nodethen(which istail.next), move it to the position afterprev, and adjust the adjacent links. For example, in1 -> 2 -> 3 -> 4 -> 5withleft = 2,right = 4:
prev = 1,tail = 2.- First step (
then = 3):1 -> 3 -> 2 -> 4 -> 5. - Second step (
then = 4):1 -> 4 -> 3 -> 2 -> 5. This reverses the sub-list in a single pass with O(1) extra memory.
Solution 1: Single Pass In-Place Reversal
Track boundaries using link pointers and shift sub-segment nodes step by step.
/**
* 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) return null;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
// Move prev to position left - 1
for (int i = 0; i < left - 1; i++) {
prev = prev.next;
}
ListNode tail = prev.next; // first node of the sub-list to reverse
// Reverse sub-list in place
for (int i = 0; i < right - left; i++) {
ListNode then = tail.next;
tail.next = then.next;
then.next = prev.next;
prev.next = then;
}
return dummy.next;
}
}# 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:
return None
dummy = ListNode(0)
dummy.next = head
prev = dummy
# Move prev to position left - 1
for _ in range(left - 1):
prev = prev.next
tail = prev.next # first node of sub-list to reverse
# Reverse sub-list
for _ in range(right - left):
then = tail.next
tail.next = then.next
then.next = prev.next
prev.next = then
return dummy.next/**
* 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) return nullptr;
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* prev = dummy;
for (int i = 0; i < left - 1; i++) {
prev = prev->next;
}
ListNode* tail = prev->next;
for (int i = 0; i < right - left; i++) {
ListNode* then = tail->next;
tail->next = then->next;
then->next = prev->next;
prev->next = then;
}
return dummy->next;
}
};Complexity Analysis
- Time Complexity: O(n) since we traverse the list nodes at most once.
- Space Complexity: O(1) auxiliary space as the reversal is performed in-place.
Where It Breaks
If the list is doubly-linked, the back pointers (prev) must be updated in tandem, otherwise the list structure is broken.
Common Mistakes
- Incorrect index offsets: Forgetting the dummy node wrapper. Without a dummy node, if
left = 1,prevwill be null, causing a null pointer dereference. - Wrong link assignments: Swapping
tail.nextandthen.nextincorrectly, causing nodes to be dropped or creating infinite cycles.
Frequently Asked Questions
Why is a dummy node necessary here?
If left = 1, the head of the list itself is reversed. A dummy node provides a stable parent link to the new head.
How does this behave if left == right?
The inner loop right - left runs 0 times, so no nodes are modified, and the original list is returned as is.