Reverse Linked List II
MedPrompt
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
3 approaches with complexity analysis and trade-offs.
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.
Walkthrough
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
Time
O(N)
Space
O(1)
Trade-offs
Pros
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.
Cons
The pointer manipulation can be complex and non-intuitive to understand and implement correctly without careful visualization.
Solutions
Solution
/** * 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 walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.