Problem
Reverse a linked list from position m to n. Do it in-place and in one-pass.
OR
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:
--- title: Input --- graph LR A1[1] --> B2[2]:::reversed --> C3[3]:::reversed --> D4[4]:::reversed --> E5[5] classDef reversed fill:#ffcc00,stroke:#000,stroke-width:2px;
--- title: Output --- graph LR A1[1] --> D4[4]:::reversed --> C3[3]:::reversed --> B2[2]:::reversed --> E5[5] classDef reversed fill:#ffcc00,stroke:#000,stroke-width:2px;
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]
Note:
Given m, n satisfy the following condition: 1 ≤ m ≤ n ≤ length of list.
Note 2:
Usually the version often seen in the interviews is reversing the whole linked list which is obviously an easier version of this question.
Solution
Method 1 - Iteration
Here is the approach:
- Initialization:
- Use a dummy node to handle edge cases where the reversal might include the head node.
- Use pointers to keep track of the node just before the reverse segment and the end of the reverse segment.
- Move to Start of Reversal Segment:
- Move a pointer to the
left-1
position.
- Move a pointer to the
- Reverse the Segment:
- Reverse the nodes between
left
andright
.
- Reverse the nodes between
- Reconnect the Links:
- Reconnect the reversed segment back into the original list.
Code
Java
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
if (head == null || left == right)
return head;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
// Move prev to the node before the left position
for (int i = 0; i < left - 1; i++) {
prev = prev.next;
}
ListNode start = prev.next;
ListNode then = start.next;
// Reverse the sublist using insertion technique
for (int i = 0; i < right - left; i++) {
start.next = then.next;
then.next = prev.next;
prev.next = then;
then = start.next;
}
return dummy.next;
}
}
Python
class Solution:
def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
if not head or left == right:
return head
dummy = ListNode(0)
dummy.next = head
prev = dummy
# Move prev to the node before the left position
for _ in range(left - 1):
prev = prev.next
start = prev.next
then = start.next
# Reverse the sublist using insertion technique
for _ in range(right - left):
start.next = then.next
then.next = prev.next
prev.next = then
then = start.next
return dummy.next
Complexity
- ⏰ Time complexity:
O(n)
, wheren
is the number of nodes in the linked list. Each node is processed at most twice. - 🧺 Space complexity:
O(1)
, as we only use a constant amount of extra space for pointers.