Convert Sorted List to Binary Search Tree

MediumDivide and Conquer · Linked List → Tree🧩 Recursion & Divide and ConquerLeetCode #109 ↗Updated

Problem

You are given the head of a singly linked list sorted in ascending order. Build a height-balanced binary search tree (every node's subtrees differ in height by at most 1) that contains exactly these values and return its root. Any valid balanced BST is accepted.
Input[-10,-3,0,5,9]Output[0,-3,9,-10,null,5]
Input[]Output[]

0 ≤ n ≤ 2·104  ·  -105 ≤ Node.val ≤ 105  ·  list is sorted ascending

Try it yourself

Java
class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
The middle value as root splits the rest into two halves of (almost) equal size — recurse and the tree is balanced. Better still: a BST's inorder is the sorted list, so build the tree in inorder and just consume list nodes one by one.
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 ForceFind Middle with Slow/Fast Each Call

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

Treat [head, tail) as the current sub-list. Slow/fast pointers find its middle, which becomes the root; recurse on [head, mid) and [mid.next, tail). Each recursion level walks O(n) nodes in total, and there are O(log n) levels.

Java
public TreeNode sortedListToBST(ListNode head) {
    return build(head, null);
}
private TreeNode build(ListNode head, ListNode tail) {
    if (head == tail) return null;
    ListNode slow = head, fast = head;
    while (fast != tail && fast.next != tail) {
        slow = slow.next;
        fast = fast.next.next;
    }
    TreeNode root = new TreeNode(slow.val);
    root.left = build(head, slow);
    root.right = build(slow.next, tail);
    return root;
}

No extra memory besides the recursion, but re-scans the list on every level.

At a glance

LevelApproachTimeSpace
Brute ForceFind Middle with Slow/Fast Each CallO(n log n)O(log n)
BetterCopy to Array, then Binary SplitO(n)O(n)
OptimalInorder Simulation (Consume the List)O(n)O(log n)
Common pitfalls
  • Slow/fast loop that ignores tail — the middle is found in the wrong range.
  • Inorder version: creating the root before building the left subtree takes the wrong value.
  • Not cutting/limiting the range — infinite recursion on a 1-node sub-list.
Interview tips
  • Start from “sorted array to BST” (LC 108) and ask what changes without random access.
  • Explain why the slow/fast version is O(n log n): O(n) scanning per level, log n levels.
  • Present the inorder trick as the follow-up that removes both the scan and the array.
Pattern
Middle as root (divide & conquer) → build balanced trees from sorted data; inorder order = sorted order.
My notes saved in this browser