Skip to content

Reverse Linked List II

Given the head of a 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.

InputleftrightOutputExplanation
1→2→3→4→5→null241→4→3→2→5→nullReverse nodes 2, 3, 4
5→null115→nullSingle node, no reversal needed
1→2→null122→1→nullReverse the entire list
  • The number of nodes in the list is n.
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n
ApproachTimeSpaceBest When
Iterative (Pointers)O(n)O(1)Interview favorite; intuitive pointer manipulation
RecursiveO(n)O(n)More elegant; stack tracks position
  • Learn Iterative with Pointers first — it is the most common interview approach and demonstrates pointer mastery.
  • Understand Recursive as a bonus — it showcases elegant backtracking and position tracking.
Interview Favorite
Iterative with Pointers
O(n) time · O(1) space
Elegant & Recursive
Recursive
O(n) time · O(n) space
★ Recommended

Use a dummy node pointing to the head to simplify edge cases. Advance to position left - 1 (the node before the reversal). Then, perform right - left reversals by moving nodes to the front of the sublist.

⏱ Time O(n) Single pass through list 💾 Space O(1) Pointer variables only

Input: 1→2→3→4→5→null, left = 2, right = 4

StepActionList State
Create dummyDummy points to 1dummy→1→2→3→4→5→null
Advance prev to node 1Move left-1 timesprev=1, curr=2
Reverse 1→2→4Move 2 in front1→3→2→4→5→null
Reverse 1→3→4Move 3 in front1→4→3→2→5→null
Connect tailEnsure 2→51→4→3→2→5→null

Animated walkthrough

How iterative pointer reversal works step-by-step

Use Next or Autoplay to see the dummy node, pointer positioning, and the reversal loop in action.

Step 1 of 4
Waiting to begin...
Array state
Memory / lookup state

function reverseBetween(head, left, right):
if left == right:
return head
dummy = ListNode(0, head)
prev = dummy
# Advance prev to position left-1
for i in range(left - 1):
prev = prev.next
curr = prev.next
# Reverse right - left times
for i in range(right - left):
next_temp = curr.next
curr.next = next_temp.next
next_temp.next = prev.next
prev.next = next_temp
return dummy.next
reverse_linked_list_ii_iterative.py
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]:
"""
Reverse a portion of a linked list from position left to right (1-indexed).
Time Complexity: O(n) - single pass through the list
Space Complexity: O(1) - only pointer variables
Strategy:
1. Create a dummy node to handle edge case of reversing from head
2. Advance prev pointer to position left-1
3. Perform (right - left) reversals by moving nodes to the front of the sublist
4. Return dummy.next
"""
if left == right:
return head
# Create dummy node pointing to head
dummy = ListNode(0, head)
prev = dummy
# Advance prev to position left-1
for _ in range(left - 1):
prev = prev.next
# curr is the first node to reverse (at position left)
curr = prev.next
# Perform (right - left) reversals
for _ in range(right - left):
# next_temp is the node we want to move to the front
next_temp = curr.next
# Bypass next_temp by connecting curr to next_temp.next
curr.next = next_temp.next
# Move next_temp to the front of the sublist
next_temp.next = prev.next
prev.next = next_temp
return dummy.next
# Test cases
def list_to_array(head: Optional[ListNode]) -> list:
"""Convert linked list to array for easy comparison."""
result = []
while head:
result.append(head.val)
head = head.next
return result
def array_to_list(arr: list) -> Optional[ListNode]:
"""Convert array to linked list."""
if not arr:
return None
head = ListNode(arr[0])
current = head
for val in arr[1:]:
current.next = ListNode(val)
current = current.next
return head
# Test 1: Reverse middle portion
head1 = array_to_list([1, 2, 3, 4, 5])
result1 = reverseBetween(head1, 2, 4)
print(list_to_array(result1)) # [1, 4, 3, 2, 5]
# Test 2: Single node (no reversal)
head2 = array_to_list([5])
result2 = reverseBetween(head2, 1, 1)
print(list_to_array(result2)) # [5]
# Test 3: Reverse entire list
head3 = array_to_list([1, 2])
result3 = reverseBetween(head3, 1, 2)
print(list_to_array(result3)) # [2, 1]
# Test 4: Reverse from start
head4 = array_to_list([1, 2, 3, 4, 5])
result4 = reverseBetween(head4, 1, 3)
print(list_to_array(result4)) # [3, 2, 1, 4, 5]
# Test 5: Reverse at end
head5 = array_to_list([1, 2, 3, 4, 5])
result5 = reverseBetween(head5, 3, 5)
print(list_to_array(result5)) # [1, 2, 5, 4, 3]
elegant

Recursively advance to position left. At that point, reverse nodes one at a time as the call stack unwinds, tracking when to stop at position right.

⏱ Time O(n) Traverse to left, reverse to right 💾 Space O(n) Recursion call stack

Instead of explicit pointer swaps, recursion naturally tracks the “current position.” When we reach position left, we begin the reversal. As we unwind (backtrack), we reverse links and stop after right - left reversals.

Input: 1→2→3→4→5→null, left = 2, right = 4

StepDepthNodeAction
Go deep1Node 1Recurse to node 2
Go deep2Node 2Recurse to node 3 (mark as reversal start)
Go deep3Node 3Recurse to node 4
Go deep4Node 4Recurse to node 5
Unwind4Node 4→5Reverse: 4.next.next = 4 (stop here, right=4)
Unwind3Node 3→4Reverse: 3.next.next = 3
Unwind2Node 2→3Reverse: 2.next.next = 2 (tail of reversed section)
Unwind1Node 1→2Connect tail; return
function reverseBetween(head, left, right):
if left == 1:
return reverseN(head, right)
else:
head.next = reverseBetween(head.next, left - 1, right - 1)
return head
function reverseN(head, n):
if n == 1:
return head
new_head = reverseN(head.next, n - 1)
head.next.next = head
head.next = successor
return new_head
reverse_linked_list_ii_recursive.py
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
# Global variable to track the successor node
successor = None
def reverseBetween(head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
"""
Reverse a portion of a linked list from position left to right using recursion.
Time Complexity: O(n) - traverse to left, then reverse to right
Space Complexity: O(n) - recursion call stack
Strategy:
1. If left == 1, call reverseN() to reverse the first 'right' nodes
2. Otherwise, recursively process the next node with adjusted positions
3. Use a global successor variable to track where to stop reversing
"""
if left == 1:
return reverseN(head, right)
else:
# Recursively process the rest of the list
head.next = reverseBetween(head.next, left - 1, right - 1)
return head
def reverseN(head: Optional[ListNode], n: int) -> Optional[ListNode]:
"""
Reverse the first n nodes of a linked list.
The global 'successor' variable tracks the node after the nth node,
which becomes the tail of the reversed sublist.
"""
global successor
if n == 1:
# Base case: mark successor as the node after the first node
successor = head.next
return head
# Recursively reverse the rest
new_head = reverseN(head.next, n - 1)
# At this point, head.next points to the (n-1)th node
# We want to reverse: head.next.next = head
head.next.next = head
# Connect head to successor (the node after position n)
head.next = successor
return new_head
# Test cases
def list_to_array(head: Optional[ListNode]) -> list:
"""Convert linked list to array for easy comparison."""
result = []
while head:
result.append(head.val)
head = head.next
return result
def array_to_list(arr: list) -> Optional[ListNode]:
"""Convert array to linked list."""
if not arr:
return None
head = ListNode(arr[0])
current = head
for val in arr[1:]:
current.next = ListNode(val)
current = current.next
return head
# Test 1: Reverse middle portion
head1 = array_to_list([1, 2, 3, 4, 5])
result1 = reverseBetween(head1, 2, 4)
print(list_to_array(result1)) # [1, 4, 3, 2, 5]
# Test 2: Single node (no reversal)
head2 = array_to_list([5])
result2 = reverseBetween(head2, 1, 1)
print(list_to_array(result2)) # [5]
# Test 3: Reverse entire list
head3 = array_to_list([1, 2])
result3 = reverseBetween(head3, 1, 2)
print(list_to_array(result3)) # [2, 1]
# Test 4: Reverse from start
head4 = array_to_list([1, 2, 3, 4, 5])
result4 = reverseBetween(head4, 1, 3)
print(list_to_array(result4)) # [3, 2, 1, 4, 5]
# Test 5: Reverse at end
head5 = array_to_list([1, 2, 3, 4, 5])
result5 = reverseBetween(head5, 3, 5)
print(list_to_array(result5)) # [1, 2, 5, 4, 3]
✓ Simple

A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.

⏱ Time O(n) Optimized complexity 💾 Space O(1) Efficient space usage
function approach3():
// Implementation approach goes here
reverse_linked_list_ii_space_optimized.py
"""
Solution for Reverse Linked List II
"""
def solve():
"""Implementation for approach 3 of Reverse Linked List II"""
pass
if __name__ == "__main__":
print("Solution ready")