Reversal rewires each node’s next to point backward — three pointers do it in one pass.
Focus on recognizing:
“Reverse” / “reverse part of a list” → prev / cur / next dance
Pattern 1: Reverse the Entire List
Watch 1→2→3→4 rewire node by node — arrows flip, prev ends up as the new head. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Reverse A Linked List
Reverse a singly linked list — compare the iterative prev/cur/next dance with the recursive unwind.
At each node save cur.next, point cur.next at prev, then advance prev and cur. When cur is null, prev is the new head. One pass, O(1) space.
1
prev = null; cur = head
2
while cur:
3
next = cur.next // save the rest
4
cur.next = prev // flip the arrow
5
prev = cur; cur = next
6
return prev // new head
1
reverse(head):
2
if head == null || head.next == null:
3
return head // base: last node
4
newHead = reverse(head.next) // go to the end first
5
head.next.next = head // point successor back at me
6
head.next = null // cut my forward link
7
return newHead
public ListNode reverseList(ListNode head) {
ListNode prev = null, cur = head;
while (cur != null) {
ListNode next = cur.next; // save
cur.next = prev; // flip arrow
prev = cur; // advance
cur = next;
}
return prev; // new head
}def reverse_list(head):
prev, cur = None, head
while cur:
cur.next, prev, cur = prev, cur, cur.next
return prev # new headListNode* reverseList(ListNode* head) {
ListNode *prev = nullptr, *cur = head;
while (cur) {
ListNode* next = cur->next; // save
cur->next = prev; // flip arrow
prev = cur;
cur = next;
}
return prev; // new head
}function reverseList(head) {
let prev = null,
cur = head;
while (cur) {
const next = cur.next; // save
cur.next = prev; // flip arrow
prev = cur;
cur = next;
}
return prev; // new head
}Save next BEFORE flipping — otherwise the rest of the list is unreachable.
Pattern 2: Reverse Sublist [left, right]
Anchor before the window, then pull each node to the front of it. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Reverse Linked List II (Sublist)
Reverse the nodes of a linked list from position left to right, inclusive.
Park a pointer just before left, then repeatedly move the next node to the front of the window — the 'move next behind prev' shuffle — and finally reseam the tail. One pass, O(1) extra space.
1
advance prev to node before left
2
for r-l times:
3
move cur.next behind prev
4
reconnect tail
Anchor a node before left, then insert-reverse right − left + 1 nodes:
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummy = new ListNode(0, head);
ListNode before = dummy;
for (int i = 1; i < left; i++)
before = before.next; // node before sublist
ListNode prev = before.next, cur = prev.next;
for (int i = 0; i < right - left; i++) {
ListNode next = cur.next;
cur.next = prev; // flip
prev = cur;
cur = next;
}
before.next.next = cur; // tail of sublist
before.next = prev; // head of sublist
return dummy.next;
}def reverse_between(head, left, right):
dummy = ListNode(0, head)
before = dummy
for _ in range(left - 1):
before = before.next # node before sublist
prev, cur = before.next, before.next.next
for _ in range(right - left):
nxt = cur.next
cur.next = prev # flip
prev, cur = cur, nxt
before.next.next = cur # tail of sublist
before.next = prev # head of sublist
return dummy.nextListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode dummy(0, head);
ListNode* before = &dummy;
for (int i = 1; i < left; i++)
before = before->next; // node before sublist
ListNode *prev = before->next, *cur = prev->next;
for (int i = 0; i < right - left; i++) {
ListNode* next = cur->next;
cur->next = prev; // flip
prev = cur;
cur = next;
}
before->next->next = cur; // tail of sublist
before->next = prev; // head of sublist
return dummy.next;
}function reverseBetween(head, left, right) {
const dummy = new ListNode(0, head);
let before = dummy;
for (let i = 1; i < left; i++) before = before.next;
let prev = before.next,
cur = prev.next;
for (let i = 0; i < right - left; i++) {
const next = cur.next;
cur.next = prev; // flip
prev = cur;
cur = next;
}
before.next.next = cur; // tail of sublist
before.next = prev; // head of sublist
return dummy.next;
}The dummy node means “reverse starting at index 1” needs no special case.
Pattern 3: Reverse Nodes in K-Group
Probe k ahead first; partial groups stay untouched. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Reverse Nodes In K-Group
Reverse nodes of a linked list in groups of k; leave any partial trailing group as-is.
Probe k nodes ahead; if a full group exists, reverse it in place and stitch it to the previous group's tail, then recurse from the new group tail. A leftover group shorter than k is appended unchanged.
1
probe k nodes ahead — enough left?
2
no → append rest, stop
3
yes → reverse this group
4
prevGroup.next = new head
5
recurse from group tail
Reverse k at a time; leave the tail partial group untouched:
public ListNode reverseKGroup(ListNode head, int k) {
// check there are k nodes left
ListNode node = head;
for (int i = 0; i < k; i++) {
if (node == null) return head; // not enough
node = node.next;
}
// reverse exactly k
ListNode prev = null, cur = head;
for (int i = 0; i < k; i++) {
ListNode next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
head.next = reverseKGroup(cur, k); // recurse on the rest
return prev;
}def reverse_k_group(head, k):
# check there are k nodes left
node = head
for _ in range(k):
if not node:
return head # not enough
node = node.next
# reverse exactly k
prev, cur = None, head
for _ in range(k):
cur.next, prev, cur = prev, cur, cur.next
head.next = reverse_k_group(cur, k) # recurse on the rest
return prevListNode* reverseKGroup(ListNode* head, int k) {
// check there are k nodes left
ListNode* node = head;
for (int i = 0; i < k; i++) {
if (!node) return head; // not enough
node = node->next;
}
// reverse exactly k
ListNode *prev = nullptr, *cur = head;
for (int i = 0; i < k; i++) {
ListNode* next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
head->next = reverseKGroup(cur, k); // recurse on the rest
return prev;
}function reverseKGroup(head, k) {
// check there are k nodes left
let node = head;
for (let i = 0; i < k; i++) {
if (!node) return head; // not enough
node = node.next;
}
// reverse exactly k
let prev = null,
cur = head;
for (let i = 0; i < k; i++) {
const next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
head.next = reverseKGroup(cur, k); // recurse on the rest
return prev;
}Pre-check k availability first — reversing then discovering you can’t finish leaves a mess.
Common Mistakes
Flipping before saving next.
The remainder of the list is lost forever.
Forgetting to reconnect the reversed sublist.
Sublist reversal must stitch both ends back: before.next = newHead and subTail.next = after.
Returning head after full reversal.
Return prev — the original head is now the LAST node.
Complexity
| Operation | Time | Space |
|---|---|---|
| Full reverse | O(n) | O(1) |
| Sublist | O(n) | O(1) |
| K-group | O(n) | O(n/k) recursion |
Premium Content
Unlock Reverse Linked List and all premium lessons with a subscription.
From ₹199.99/year — See plans