Reorder List
Medium · Linked List · Explanation and code example
Reverse And Merge
How it works
To reorder the list into the pattern L1 → Ln → L2 → Ln−1 → L3 → Ln−2 → ..., we can break the problem into three simple steps:
-
Find the middle of the linked list using
slowandfastpointers. This splits the list into two halves. -
Reverse the second half of the list. Doing this makes it easy to merge nodes from the front and back alternately.
-
Merge the two halves one-by-one: Take one node from the first half (
first), then one from the reversed second half (second), and repeat.
This method is clean, intuitive, and uses only O(1) extra space.
Steps
-
Find the middle:
- Use
slowandfastpointers. - When
fastreaches the end,slowwill be at the midpoint.
- Use
-
Reverse the second half:
- Start from
slow.next. - Reverse it using the standard linked-list reversal approach with
prevandtmpvariables.
- Start from
-
Merge the two lists:
- Take a node from
firsthalf. - Take a node from the reversed
secondhalf. - Continue until
secondis exhausted.
- Take a node from
This produces the desired reordered list in-place with no extra memory.
Complexity
- Time complexity:
O(n) - Space complexity:
O(1)
Things to watch for
Incorrectly Finding the Middle Node
The slow/fast pointer technique must be initialized correctly. Starting both pointers at head versus starting fast at head.next affects whether slow ends at the last node of the first half or the first node of the second half. This off-by-one error leads to incorrect splitting and malformed results.
Forgetting to Disconnect the Two Halves
After finding the middle, you must set slow.next = None to split the list into two independent halves. Without this, the reversal step creates a cycle or corrupts the original list structure, causing infinite loops during merging.
Losing References During Merge
When interleaving nodes from the first and second halves, each next pointer reassignment breaks the original chain. Failing to save tmp1 = first.next and tmp2 = second.next before modifying pointers causes you to lose track of remaining nodes, resulting in an incomplete or broken list.
Python code example
from typing import Optional
# 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: Optional[ListNode]) -> None:
slow, fast = head, head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
second = slow.next
prev = slow.next = None
while second:
tmp = second.next
second.next = prev
prev = second
second = tmp
first, second = head, prev
while second:
tmp1, tmp2 = first.next, second.next
first.next = second
second.next = tmp1
first, second = tmp1, tmp2
C++ code example
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head->next;
while (fast != nullptr && fast->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
}
ListNode* second = slow->next;
ListNode* prev = slow->next = nullptr;
while (second != nullptr) {
ListNode* tmp = second->next;
second->next = prev;
prev = second;
second = tmp;
}
ListNode* first = head;
second = prev;
while (second != nullptr) {
ListNode* tmp1 = first->next;
ListNode* tmp2 = second->next;
first->next = second;
second->next = tmp1;
first = tmp1;
second = tmp2;
}
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.