🧠
Recursive Reversal with Helper Function (Tail Recursion Style)
💡 This approach uses a helper function with extra parameters to carry previous and current nodes, simulating iteration with recursion. It helps understand how recursion can mimic iteration.
Intuition
Pass previous and current nodes as parameters, reverse current's pointer to previous, and recurse forward until the end.
Algorithm
- Define a helper function that takes previous and current nodes.
- If current is null, return previous as new head.
- Save next node.
- Reverse current's next pointer to previous.
- Recurse with current as previous and next as current.
- Call helper with null and head initially.
💡 This approach is a recursive version of the iterative method, making the pointer changes explicit in recursion parameters.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverseList(head):
def helper(prev, curr):
if not curr:
return prev
next_temp = curr.next
curr.next = prev
return helper(curr, next_temp)
return helper(None, head)
# Driver code
if __name__ == '__main__':
head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
new_head = reverseList(head)
curr = new_head
while curr:
print(curr.val, end=' ')
curr = curr.next
print()
Line Notes
def helper(prev, curr):Helper function carries previous and current nodes for recursion
if not curr:Base case: reached end of list, return previous as new head
next_temp = curr.nextSave next node before reversing pointer
curr.next = prevReverse current node's pointer to previous
return helper(curr, next_temp)Recurse forward with updated pointers
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; }
}
public class Solution {
public ListNode reverseList(ListNode head) {
return helper(null, head);
}
private ListNode helper(ListNode prev, ListNode curr) {
if (curr == null) return prev;
ListNode nextTemp = curr.next;
curr.next = prev;
return helper(curr, nextTemp);
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
Solution sol = new Solution();
ListNode newHead = sol.reverseList(head);
ListNode curr = newHead;
while (curr != null) {
System.out.print(curr.val + " ");
curr = curr.next;
}
System.out.println();
}
}
Line Notes
return helper(null, head);Start recursion with previous null and current head
if (curr == null) return prev;Base case: end of list reached, return previous as new head
ListNode nextTemp = curr.next;Save next node before reversing pointer
curr.next = prev;Reverse current node's pointer to previous
return helper(curr, nextTemp);Recurse forward with updated pointers
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
ListNode* helper(ListNode* prev, ListNode* curr) {
if (!curr) return prev;
ListNode* nextTemp = curr->next;
curr->next = prev;
return helper(curr, nextTemp);
}
ListNode* reverseList(ListNode* head) {
return helper(nullptr, head);
}
};
int main() {
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(3);
head->next->next->next = new ListNode(4);
head->next->next->next->next = new ListNode(5);
Solution sol;
ListNode* newHead = sol.reverseList(head);
ListNode* curr = newHead;
while (curr) {
cout << curr->val << " ";
curr = curr->next;
}
cout << endl;
return 0;
}
Line Notes
if (!curr) return prev;Base case: end of list reached, return previous as new head
ListNode* nextTemp = curr->next;Save next node before reversing pointer
curr->next = prev;Reverse current node's pointer to previous
return helper(curr, nextTemp);Recurse forward with updated pointers
return helper(nullptr, head);Start recursion with previous null and current head
class ListNode {
constructor(val, next = null) {
this.val = val;
this.next = next;
}
}
function reverseList(head) {
function helper(prev, curr) {
if (!curr) return prev;
let nextTemp = curr.next;
curr.next = prev;
return helper(curr, nextTemp);
}
return helper(null, head);
}
// Driver code
const head = new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(4, new ListNode(5)))));
const newHead = reverseList(head);
let curr = newHead;
let output = '';
while (curr) {
output += curr.val + ' ';
curr = curr.next;
}
console.log(output.trim());
Line Notes
function helper(prev, curr) {Helper function carries previous and current nodes for recursion
if (!curr) return prev;Base case: end of list reached, return previous as new head
let nextTemp = curr.next;Save next node before reversing pointer
curr.next = prev;Reverse current node's pointer to previous
return helper(curr, nextTemp);Recurse forward with updated pointers
Each node visited once, recursion stack depth is n
💡 Similar to pure recursion, but parameters make pointer changes clearer; still risks stack overflow for large n.
Interview Verdict: Accepted but less preferred than iterative
Good for understanding recursion with parameters, but iterative is safer and more common in interviews.