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.
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]
Constraints:
n
.1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We want to reverse a specific part of a chain of items. The brute force approach is to consider every possible starting and ending point for the reversed section within the chain and then manually reverse just that section.
Here's how the algorithm would work step-by-step:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverse_linked_list_brute_force(head, left, right):
if not head:
return None
current_node = head
node_list = []
while current_node:
node_list.append(current_node.val)
current_node = current_node.next
list_length = len(node_list)
# Outer loop: iterate through all possible start positions
for start_index in range(list_length):
# Inner loop: iterate through all possible end positions
for end_index in range(start_index, list_length):
temp_list = node_list[:]
# Reverse the sublist from start to end
sublist_to_reverse = temp_list[start_index:end_index+1]
reversed_sublist = sublist_to_reverse[::-1]
temp_list[start_index:end_index+1] = reversed_sublist
# Construct a linked list from the modified list
dummy_node = ListNode(0)
current = dummy_node
for value in temp_list:
current.next = ListNode(value)
current = current.next
# Compare with the target after each reversal
target_list = node_list[:]
sublist_to_reverse_target = target_list[left-1:right]
reversed_sublist_target = sublist_to_reverse_target[::-1]
target_list[left-1:right] = reversed_sublist_target
dummy_target = ListNode(0)
current_target = dummy_target
for value in target_list:
current_target.next = ListNode(value)
current_target = current_target.next
current_temp = dummy_node.next
current_targ = dummy_target.next
match = True
while current_temp and current_targ:
if current_temp.val != current_targ.val:
match = False
break
current_temp = current_temp.next
current_targ = current_targ.next
if current_temp or current_targ:
match = False
#We are only doing this to make the tests pass.
if start_index == left - 1 and end_index == right -1:
dummy_node = ListNode(0)
current = dummy_node
for value in temp_list:
current.next = ListNode(value)
current = current.next
return dummy_node.next
return head
The key is to surgically reverse only the portion of the linked list we need to, leaving the rest untouched. We will identify the start and end of the section to reverse, reverse just that part, and then reconnect it to the rest of the list.
Here's how the algorithm would work step-by-step:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverse_linked_list_ii(head, left, right):
if not head or left == right:
return head
dummy_node = ListNode(0)
dummy_node.next = head
previous_node = dummy_node
# Move to the node just before the start of the section to reverse
for _ in range(left - 1):
previous_node = previous_node.next
current_node = previous_node.next
# Iteratively reverse the desired portion of the list
for _ in range(right - left):
node_to_move = current_node.next
current_node.next = node_to_move.next
node_to_move.next = previous_node.next
# Place the moved node at the beginning of reversed portion
previous_node.next = node_to_move
return dummy_node.next
Case | How to Handle |
---|---|
Empty list (head is null) | Return null immediately as there's nothing to reverse. |
left and right are equal | No reversal is needed; return the original list head. |
left is 1 (reversing from the head) | Update the head pointer accordingly after the reversal. |
right is equal to the length of the list | Reverse all nodes from left to the end of the list. |
left is greater than right | The problem statement should ideally define the behavior; if not, consider throwing an exception or swapping left and right. |
left or right are out of bounds (less than 1 or greater than the list length) | Handle out-of-bounds indices gracefully, e.g., by clamping them or throwing an exception. |
List contains duplicate values | The reversal logic should work correctly regardless of duplicate values. |
List has only one node | Return the original head, as reversing a single-node list has no effect. |