Reverse Linked List

Given the head of a singly linked list, reverse the list, and return the reversed list.

Example case

the below shows the expected result after running our function

The ‘move’

The main technique for solving this question is:

Two phases of recursion

The first one is descending. Each movement(recursive call) creates a new stack frame.

The second one is ascending. Unwinding the recursion.

Touching the base of recursion

if (head == null || head.next == null) {
    return head;
  }
  ListNode reversedListHead = reverseList(head.next);

This portion of the code makes us go until the end of the linked list.

Touching the base of recursion. Each green rectangle is a new stack frame
the blue arrows indicate what it returns to previous stack frame

Example running

Let’s take the stack frame when the head is 4 in ascending phase.

when the head is 4:

when the head is 3:

The code

public ListNode reverseList(ListNode head) {
  if (head == null || head.next == null) {
    return head;
  }

  ListNode reversedListHead = reverseList(head.next);
  head.next.next = head;
  head.next = null;
  return reversedListHead;
}
  • Recursive Descent: This is the phase where the recursion is "unfolding," meaning the function is making recursive calls and diving deeper into the problem space, moving towards the base case. This corresponds to what you've called the "descending phase."
  • Recursive Ascent (sometimes just referred to as "returning" or "unwinding the recursion"): This is the phase where the recursion is "folding back up," meaning the function is now returning from the base case, and the recursive calls are resolving back up the call stack. This corresponds to what you've called the "ascending phase."

Post-Solution Insights

 func(ListNode head){
	 if (head == null || head.next == null) {
    return head;
   }
	 ListNode reversedListHead = reverseList(head.next);
	 return reversedListHead;
 }
 

These two lines of code are crucial because, with them, we can traverse all the way to the end of the linked list, capturing the last node. Then, as we return through each stack frame, we effectively bring this last node back to the first stack frame, where the fully reversed list is returned.

Leave a Comment