143. Reorder List
At a Glance
- Topic: linked-list
- Pattern: In-place Linked List Reversal + merge
- Difficulty: Medium
- Companies: Facebook, Amazon, Google, Microsoft, Oracle
- Frequency: High
- LeetCode: 143
Problem (one-liner)
Given a singly linked list, reorder nodes to L0 -> Ln -> L1 -> Ln-1 -> ... in place without extra O(n) space for new nodes (only pointer churn).
Recognition Cues
- “Interleave first and last” on a list
- Three steps: find middle, reverse second half, merge two lists
- Linear time,
O(1)extra
Diagram
At-a-glance flow (replace with problem-specific Mermaid as you refine this note). camelCase node IDs; no spaces in IDs.
Loading diagram…
Approaches
- Brute force —
O(n)time /O(n)space — copy to array, rewrite indices. - Better — two passes with stack for second half —
O(n)space. - Optimal —
O(n)time /O(1)space — slow/fast for mid, reverse tail, merge like two sorted lists but always take from alternating heads.
Optimal Solution
Go
type ListNode struct {
Val int
Next *ListNode
}
func reorderList(head *ListNode) {
if head == nil || head.Next == nil {
return
}
slow, fast := head, head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
second := slow.Next
slow.Next = nil
second = reverseList(second)
mergeInterleave(head, second)
}
func reverseList(head *ListNode) *ListNode {
var previous *ListNode
current := head
for current != nil {
next := current.Next
current.Next = previous
previous = current
current = next
}
return previous
}
func mergeInterleave(first *ListNode, second *ListNode) {
for second != nil {
nextFirst := first.Next
nextSecond := second.Next
first.Next = second
second.Next = nextFirst
first = nextFirst
second = nextSecond
}
}JavaScript
class ListNode {
constructor(val = 0, next = null) {
this.val = val;
this.next = next;
}
}
function reorderList(head) {
if (head === null || head.next === null) {
return;
}
let slow = head;
let fast = head;
while (fast !== null && fast.next !== null) {
slow = slow.next;
fast = fast.next.next;
}
let second = slow.next;
slow.next = null;
second = reverseList(second);
mergeInterleave(head, second);
}
function reverseList(head) {
let previous = null;
let current = head;
while (current !== null) {
const next = current.next;
current.next = previous;
previous = current;
current = next;
}
return previous;
}
function mergeInterleave(first, second) {
while (second !== null) {
const nextFirst = first.next;
const nextSecond = second.next;
first.next = second;
second.next = nextFirst;
first = nextFirst;
second = nextSecond;
}
}Walkthrough
1 -> 2 -> 3 -> 4
| phase | result |
|---|---|
| mid split | 1->2 and 4->3 (reversed) |
| merge | 1->4->2->3 |
Invariant: first half length equals or exceeds second; merge always has a node from first to splice after.
Edge Cases
- Length 1 or 2 — no visible change or single swap path still works.
- Odd length — middle element naturally ends at tail after merge.
Pitfalls
- Forgetting to cut list at
slow.Next = nil— creates cycles. - Reversing full list instead of second half only.
Similar Problems
- 206. Reverse Linked List — reverses second segment.
- 234. Palindrome Linked List — also splits mid + reverse half.
- 21. Merge Two Sorted Lists — merge discipline without key comparison.
Variants
k-way interleave — extend merge round-robin.- Array input — same pointer story after building list.
Mind-Map Tags
#linked-list #split-list #reverse-half #interleave-merge
Last updated on
Spotted something unclear or wrong on this page?