Reverse Linked List II
MEDIUMDescription
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:
- The number of nodes in the list is
n. 1 <= n <= 500-500 <= Node.val <= 5001 <= left <= right <= n
Follow up: Could you do it in one pass?
Approaches
Checkout 3 different approaches to solve Reverse Linked List II. Click on different approaches to view the approach and algorithm in detail.
Iterative In-place Reversal (One Pass)
This is the most optimal approach, solving the problem in a single pass with constant extra space. It involves careful pointer manipulation to reverse the sublist directly within the original list.
Algorithm
- Create a
dummynode and setdummy.next = head. This simplifies handling the edge case whereleft = 1. - Create a pointer
pre_leftand initialize it todummy. - Move
pre_leftforwardleft - 1times. After the loop,pre_leftwill be at the node just before the sublist to be reversed. - Initialize
current = pre_left.next. Thiscurrentpointer marks the start of the sublist to be reversed and will eventually become its tail. - Loop
right - lefttimes. This is the core of the reversal:- a. Let
node_to_move = current.next. This is the node we will move to the front of the reversed section. - b. Detach
node_to_movefrom its current position by settingcurrent.next = node_to_move.next. - c. Prepend
node_to_moveto the reversed part by settingnode_to_move.next = pre_left.next. - d. Update the link from the preceding part of the list by setting
pre_left.next = node_to_move.
- a. Let
- After the loop completes, the sublist from
lefttorightis reversed and correctly linked with the rest of the list. - Return
dummy.next, which is the head of the modified list.
This iterative approach is the standard and most efficient solution. It directly manipulates the node pointers in-place to achieve the reversal.
- We use a
dummynode to simplify edge cases, such as when the reversal starts at the head of the list (left = 1). Thedummynode points to the originalhead. - First, we iterate
left - 1times to find the node just before the sublist to be reversed. Let's call thispre_left. - We then identify the start of our sublist,
current = pre_left.next. Thiscurrentnode will act as a pivot and will become the tail of the reversed sublist after all operations. - We then loop
right - lefttimes. In each iteration, we take the node immediately followingcurrent(let's call itnode_to_move) and move it to become the new first node of the sublist (i.e., right afterpre_left).
Let's trace [1,2,3,4,5], left=2, right=4:
- Initial:
dummy -> 1 -> 2 -> 3 -> 4 -> 5.pre_leftis at1,currentis at2. - Iteration 1 (move
3):node_to_moveis3. The list becomesdummy -> 1 -> 3 -> 2 -> 4 -> 5. - Iteration 2 (move
4):node_to_moveis4. The list becomesdummy -> 1 -> 4 -> 3 -> 2 -> 5.
After the loop, the sublist is reversed, and all connections are correctly updated. We return dummy.next.
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;
// 1. Reach node at position `left - 1`
ListNode pre_left = dummy;
for (int i = 0; i < left - 1; i++) {
pre_left = pre_left.next;
}
// 2. `current` points to the node at position `left`
ListNode current = pre_left.next;
// 3. Reverse the sublist
for (int i = 0; i < right - left; i++) {
ListNode node_to_move = current.next;
current.next = node_to_move.next;
node_to_move.next = pre_left.next;
pre_left.next = node_to_move;
}
return dummy.next;
}
}
Complexity Analysis
Pros and Cons
- Optimal O(1) space complexity as it only uses a few extra pointers.
- Highly efficient single-pass solution with O(N) time complexity.
- Handles all edge cases gracefully, especially with the use of a dummy node.
- The pointer manipulation can be complex and non-intuitive to understand and implement correctly without careful visualization.
Code Solutions
Checking out 5 solutions in different languages for Reverse Linked List II. Click on different languages to view the code.
/** * Definition for singly-linked list. * public class ListNode { * public int val; * public ListNode next; * public ListNode(int val=0, ListNode next=null) { * this.val = val; * this.next = next; * } * } */ public class Solution { public ListNode ReverseBetween ( ListNode head , int left , int right ) { if ( head . next == null || left == right ) { return head ; } ListNode dummy = new ListNode ( 0 , head ); ListNode pre = dummy ; for ( int i = 0 ; i < left - 1 ; ++ i ) { pre = pre . next ; } ListNode p = pre ; ListNode q = pre . next ; ListNode cur = q ; for ( int i = 0 ; i < right - left + 1 ; ++ i ) { ListNode t = cur . next ; cur . next = pre ; pre = cur ; cur = t ; } p . next = pre ; q . next = cur ; return dummy . next ; } }Video Solution
Watch the video walkthrough for Reverse Linked List II
Similar Questions
5 related questions you might find useful
Data Structures:
Companies:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.