The problem. Given the head of a singly linked list, return it sorted in ascending order. Aim for O(n log n) time.
4 -> 2 -> 1 -> 3 -> 1 -> 2 -> 3 -> 4
-1 -> 5 -> 3 -> 4 -> 0 -> -1 -> 0 -> 3 -> 4 -> 5
(empty) -> (empty)Quick sort and heap sort jump around by index, which a linked list can't do. Merge sort only ever walks forwards: finding the middle takes a slow and a fast pointer, splitting is one next = null, and merging two sorted lists just relinks existing nodes — no extra array, no copying. That makes it the standard way to sort a linked list.
function sortList(head) { const values = []; for (let node = head; node !== null; node = node.next) values.push(node.val); values.sort((a, b) => a - b); let i = 0; for (let node = head; node !== null; node = node.next) node.val = values[i++]; // write them back in order return head;}Time O(n log n), space O(n). It works, but it needs an array as big as the list, and it changes the values rather than the links — which interviewers usually rule out.
Cut the list at the middle, sort both halves, then merge them by relinking nodes.
function sortList(head) { if (head === null || head.next === null) return head; // 0 or 1 nodes: sorted let slow = head, fast = head.next; // find the middle while (fast !== null && fast.next !== null) { slow = slow.next; fast = fast.next.next; } const right = slow.next; slow.next = null; // cut the list in two return mergeLists(sortList(head), sortList(right));} function mergeLists(a, b) { const dummy = new ListNode(0); let tail = dummy; while (a !== null && b !== null) { if (a.val <= b.val) { tail.next = a; a = a.next; } else { tail.next = b; b = b.next; } tail = tail.next; } tail.next = a !== null ? a : b; // attach whatever is left return dummy.next;}Time O(n log n), space O(log n) for the recursion. Starting fast at head.next makes slow stop at the end of the left half, so a two-node list splits into one and one instead of looping forever. A bottom-up version — merge runs of 1, then 2, then 4, … — removes the recursion and reaches O(1) extra space.
fast at head.next).<= keeps it stable.