THN Interview Prep

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 forceO(n) time / O(n) space — copy to array, rewrite indices.
  • Better — two passes with stack for second half — O(n) space.
  • OptimalO(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

phaseresult
mid split1->2 and 4->3 (reversed)
merge1->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

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?

On this page