45. Reorder List
Problem Statement
You are given the head of a singly linked list L
: L0 → L1 → ... → Ln-1 → Ln
.
Reorder the list to be on the following form: L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → ...
You may not modify the values in the list's nodes. Only nodes themselves may be changed.
Example 1:
Input: head = [1,2,3,4] Output: [1,4,2,3]
Example 2:
Input: head = [1,2,3,4,5] Output: [1,5,2,4,3]
Solution
# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if not head or not head.next:
return
# Step 1: Find the middle of the linked list
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# slow is now at the middle node
# Step 2: Split the list into two halves
# first_half: head -> ... -> slow (before split)
# second_half: slow.next -> ... -> None
second_half = slow.next
slow.next = None # Break the link to separate the two halves
first_half = head
# Step 3: Reverse the second half of the list
prev = None
curr = second_half
while curr:
next_temp = curr.next
curr.next = prev
prev = curr
curr = next_temp
second_half_reversed = prev
# Step 4: Merge the two halves
# L0 -> L1 -> L2 -> ...
# Ln -> Ln-1 -> Ln-2 -> ...
# Merge: L0 -> Ln -> L1 -> Ln-1 -> ...
p1, p2 = first_half, second_half_reversed
while p2:
temp1 = p1.next
temp2 = p2.next
p1.next = p2
p2.next = temp1
p1 = temp1
p2 = temp2
Explanation
This problem requires reordering a linked list in a specific pattern. It can be broken down into three main steps:
-
Find the Middle of the Linked List:
- We use the fast and slow pointer technique. The
fast
pointer moves two steps at a time, and theslow
pointer moves one step at a time. Whenfast
reaches the end (orNone
),slow
will be at the middle of the list.
- We use the fast and slow pointer technique. The
-
Split the List into Two Halves:
- Once
slow
is at the middle, we break the link between the first half and the second half.slow.next
becomesNone
, effectively terminating the first half. - The second half starts from
slow.next
(beforeslow.next
was set toNone
).
- Once
-
Reverse the Second Half:
- We reverse the second half of the linked list. This is a standard linked list reversal operation (as seen in problem 44, "Reverse Linked List").
-
Merge the Two Halves:
- Now we have two lists: the first half (
L0 -> L1 -> L2 -> ...
) and the reversed second half (Ln -> Ln-1 -> Ln-2 -> ...
). - We merge them by alternating nodes:
L0
points toLn
,Ln
points toL1
,L1
points toLn-1
, and so on. - We use two pointers,
p1
for the first half andp2
for the reversed second half. In each step, we adjust thenext
pointers to interleave the nodes.
- Now we have two lists: the first half (
Time and Space Complexity:
- Time Complexity: O(n), where n is the number of nodes in the linked list. Each step (finding middle, splitting, reversing, merging) takes linear time.
- Space Complexity: O(1), as we are modifying the list in-place and only using a few extra pointers.