Sort List

MediumLinked List · Merge Sort🧩 Recursion & Divide and ConquerLeetCode #148 ↗Updated

Problem

Given the head of a singly linked list, rearrange it so the values are in ascending order and return the new head. Aim for O(n log n) time; ideally relink the existing nodes rather than creating new ones.
Input[4,2,1,3]Output[1,2,3,4]
Input[-1,5,3,4,0]Output[-1,0,3,4,5]
Input[]Output[]

0 ≤ n ≤ 5·104  ·  -105 ≤ Node.val ≤ 105  ·  Follow-up: O(n log n) time and O(1) extra space.

Try it yourself

Java
class Solution {
    public ListNode sortList(ListNode head) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Merge sort fits linked lists perfectly: merging two sorted lists needs only pointer rewiring (no buffer), and splitting is cheap. Doing it bottom-up (runs of 1, 2, 4, …) removes the recursion stack and meets the O(1)-space follow-up.
PatternRecursion & Divide and Conquer

Instinct If the answer for n items can be built from the same problem on halves (or smaller pieces) plus a cheap combine step - split, recurse, merge.

Memory hack Split it, trust it, stitch it - nail the base case, take the leap of faith on smaller calls, then glue their answers together.

Open the Recursion & Divide and Conquer guide →

Approaches

Brute ForceCopy Values, Sort Array, Write Back

Time O(n log n)Space O(n)

Dump all values into an array, sort it with the library, then walk the list again and overwrite each node's val in order. The node structure never changes, only the values.

Java
public ListNode sortList(ListNode head) {
    List<Integer> vals = new ArrayList<>();
    for (ListNode p = head; p != null; p = p.next) vals.add(p.val);
    Collections.sort(vals);
    int i = 0;
    for (ListNode p = head; p != null; p = p.next) p.val = vals.get(i++);
    return head;
}

Fast in practice, but O(n) extra memory and it rewrites values instead of relinking.

At a glance

LevelApproachTimeSpace
Brute ForceCopy Values, Sort Array, Write BackO(n log n)O(n)
BetterTop-Down Merge SortO(n log n)O(log n)
OptimalBottom-Up Merge Sort (Iterative)O(n log n)O(1)
Common pitfalls
  • Not cutting slow.next = null — the halves overlap and recursion never ends.
  • Bottom-up: losing the remainder — save cur = split(right, step) before merging.
  • Using < instead of <= in merge loses stability (harmless here, but say so).
Interview tips
  • Explain why merge sort (not quicksort) suits lists: no random access, merge is O(1) space.
  • Point out recursion depth is O(log n), so top-down is not strictly O(1) space.
  • Reuse “Merge Two Sorted Lists” and “Middle of the Linked List” as building blocks.
Pattern
Merge sort on linked lists → sort or merge lists in O(n log n) with only pointer rewiring.
My notes saved in this browser