Reorder List (L0→Ln→L1→Ln-1)
Initialize pointers and start recursion
Set 'left' pointer to head (node 1) and 'stop' flag to False. Begin recursive helper function with 'right' at head (node 1).
left = head
stop = False
helper(head)Recursive call: move 'right' to node 2
'right' pointer moves to next node (2) in recursion call stack, going deeper to the end of the list.
helper(right.next) # right moves from 1 to 2Recursive call: move 'right' to node 3
'right' pointer moves to node 3, continuing recursion deeper toward the list end.
helper(right.next) # right moves from 2 to 3Recursive call: move 'right' to node 4 (end)
'right' pointer moves to last node (4), reaching the deepest recursion level.
helper(right.next) # right moves from 3 to 4Unwind recursion: reorder nodes 1 and 4
On recursion return, 'left' is at node 1 and 'right' at node 4. Link node 1's next to node 4, and node 4's next to node 2. Move 'left' to node 2.
tmp = left.next
left.next = right
right.next = tmp
left = tmpUnwind recursion: check stop condition at nodes 2 and 3
Now 'right' is at node 3 and 'left' at node 2. Check if 'left' equals 'right' or 'left.next' equals 'right' to stop reordering.
if left == right or left.next == right:
right.next = None
stop = True
returnStop recursion and finalize list
Set 'right.next' to null to break the chain and prevent cycles. Set stop flag to True to end recursion.
right.next = None
stop = TrueRecursion fully unwound, reordered list ready
All recursive calls return. The list is reordered as 1 → 4 → 2 → 3 with no cycles.
return from helper callsTraverse reordered list to read output: start at node 1
Traverse the reordered list from head to print values in order: starting at node 1.
curr = head
while curr:
print(curr.val)
curr = curr.nextTraverse reordered list: move 'curr' to node 4
Move 'curr' pointer from node 1 to node 4, reading the next value in the reordered list.
curr = curr.next # move from node 1 to node 4Traverse reordered list: move 'curr' to node 2
Move 'curr' pointer from node 4 to node 2, continuing traversal of the reordered list.
curr = curr.next # move from node 4 to node 2Traverse reordered list: move 'curr' to node 3 (end)
Move 'curr' pointer from node 2 to node 3, reaching the end of the reordered list.
curr = curr.next # move from node 2 to node 3class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reorderList(head):
def helper(right):
nonlocal left, stop
if not right:
return # STEP 1: base case, end recursion
helper(right.next) # STEP 2-4: recurse to end
if stop:
return # STEP 7: stop if reordering done
if left == right or left.next == right:
right.next = None # STEP 6-7: stop condition, break cycle
stop = True
return
tmp = left.next # STEP 5: save next node after left
left.next = right # STEP 5: link left to right
right.next = tmp # STEP 5: link right to tmp
left = tmp # STEP 5: move left forward
left = head # STEP 1: initialize left pointer
stop = False # STEP 1: initialize stop flag
helper(head) # STEP 1: start recursion
# Driver code
if __name__ == '__main__':
n4 = ListNode(4)
n3 = ListNode(3, n4)
n2 = ListNode(2, n3)
n1 = ListNode(1, n2)
reorderList(n1)
curr = n1
while curr:
print(curr.val, end=' ')
curr = curr.next
print()Key Takeaways
This insight is hard to see from code alone because recursion hides the back pointer movement in the call stack.
Understanding when and why to stop is clearer when watching the pointers and links change step-by-step.
Seeing the exact pointer updates helps grasp how the list is reconstructed without losing nodes.
