You are 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 (1-indexed), and return the reversed list.
Example 1:
Input: head = [1,2,3,4,5], left = 1, right = 3
Output: [3,2,1,4,5]Example 2:
Input: head = [1,1], left = 1, right = 1
Output: [1,1]Constraints:
n.1 <= n <= 500.-500 <= Node.val <= 5001 <= left <= right <= nFollow up: Could you do it in one pass?
To reverse a portion of a linked list, we first locate the sublist boundaries, disconnect it from the rest, reverse it using standard list reversal, and reconnect the pieces. A dummy node simplifies edge cases where the reversal starts at the head. The recursive reversal handles the sublist by making each node point to its predecessor.
left (call it prev).sublist_head and traverse to find the sublist tail sublist_tail at position right.nextNode) and disconnect the sublist by setting sublist_tail.next to null.prev to the new sublist head (returned from reversal) and connect the original sublist head (now tail) to nextNode.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]:
dummy = ListNode(0)
dummy.next = head
prev = dummy
for _ in range(left - 1):
prev = prev.next
sublist_head = prev.next
sublist_tail = sublist_head
for _ in range(right - left):
sublist_tail = sublist_tail.next
next_node = sublist_tail.next
sublist_tail.next = None
reversed_sublist = self.reverseList(sublist_head)
prev.next = reversed_sublist
sublist_head.next = next_node
return dummy.next
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head:
return None
newHead = head
if head.next:
newHead = self.reverseList(head.next)
head.next.next = head
head.next = None
return newHeadThis approach uses recursion to navigate to the start of the reversal range. Once left equals 1, we reverse the first right nodes using a helper that tracks the successor node (the node after the reversed portion). The key insight is that as recursion unwinds, we can rewire pointers to achieve the reversal while maintaining the connection to the rest of the list.
left is 1, call the helper function reverseList to reverse the first right nodes.head.next and decremented left and right values, then attach the result to head.next.reverseList reverses n nodes starting from the given node:n is 1, save the successor (next node) and return current node.n - 1.successor.# 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]:
def reverseList(node, n):
if n == 1:
return node, node.next
new_head, next_node = reverseList(node.next, n - 1)
node.next.next = node
node.next = next_node
return new_head, next_node
if left == 1:
new_head, _ = reverseList(head, right)
return new_head
head.next = self.reverseBetween(head.next, left - 1, right - 1)
return headThe iterative approach follows the same structure as the first recursive solution but reverses the sublist using a loop instead of recursion. We traverse to find the boundaries, detach the sublist, reverse it in place using the standard three-pointer technique, and reconnect everything.
left - 1 steps to find prev (node before the sublist).sublist_head and traverse right - left more steps to find the sublist tail sublist_tail.nextNode and disconnect by setting sublist_tail.next to null.prev and curr pointers:curr to prev, advance both pointers.prev.next to the new head (final prev after reversal) and connect the original head (now tail) to the saved successor.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]:
dummy = ListNode(0)
dummy.next = head
prev = dummy
for _ in range(left - 1):
prev = prev.next
sublist_head = prev.next
sublist_tail = sublist_head
for _ in range(right - left):
sublist_tail = sublist_tail.next
next_node = sublist_tail.next
sublist_tail.next = None
reversed_sublist = self.reverseList(sublist_head)
prev.next = reversed_sublist
sublist_head.next = next_node
return dummy.next
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev, curr = None, head
while curr:
temp = curr.next
curr.next = prev
prev = curr
curr = temp
return prevThis approach reverses in a single pass without explicitly detaching the sublist. After finding the node before the reversal starts, we reverse links one at a time as we traverse. The key is maintaining a reference to the original sublist head (which becomes the tail after reversal) so we can reconnect it to the node following the reversed section.
left - 1 steps to position leftPrev (node before reversal) and cur (first node to reverse).right - left + 1 nodes in place:cur.next as tmpNext.cur.next to prev.prev to cur and cur to tmpNext.prev points to the new head of the reversed section and cur points to the node after it.leftPrev.next.next (original first node, now last) to cur.leftPrev.next to prev (the new head).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]:
dummy = ListNode(0, head)
leftPrev, cur = dummy, head
for _ in range(left - 1):
leftPrev, cur = cur, cur.next
prev = None
for _ in range(right - left + 1):
tmpNext = cur.next
cur.next = prev
prev, cur = cur, tmpNext
leftPrev.next.next = cur
leftPrev.next = prev
return dummy.nextWhen left equals 1, the head of the list changes after reversal. Without a dummy node pointing to the head, you lose the reference to the new head and cannot return the correct result. The dummy node provides a stable anchor that simplifies edge case handling when the reversal starts at the beginning.
After reversing the sublist, both ends must be reconnected to the rest of the list. A common mistake is connecting only one end, either forgetting to link the node before position left to the new sublist head, or forgetting to link the new sublist tail to the node after position right. Both connections are essential.
The single-pass reversal approach requires careful tracking of multiple pointers. A frequent error is updating leftPrev.next before using it to access the original sublist head. Since leftPrev.next initially points to the first node being reversed (which becomes the tail), you must save this reference or use it correctly before overwriting it with the new head.