Unique Binary Search Trees II

medium tree bst dp backtracking

Problem

Given an integer n, return every structurally unique BST that stores exactly the values 1, 2, …, n.

Inputn = 3
Output5 trees (Catalan number C₃)
For each root r in [1..n], recursively build all BSTs from [1..r-1] (left subtree) and [r+1..n] (right subtree); the cross product gives every tree rooted at r.

def generate_trees(n):
    def build(lo, hi):
        if lo > hi: return [None]
        out = []
        for r in range(lo, hi + 1):
            for L in build(lo, r - 1):
                for R in build(r + 1, hi):
                    out.append(TreeNode(r, L, R))
        return out
    return build(1, n) if n else []
function generateTrees(n) {
  if (!n) return [];
  function build(lo, hi) {
    if (lo > hi) return [null];
    const out = [];
    for (let r = lo; r <= hi; r++) {
      for (const L of build(lo, r - 1)) {
        for (const R of build(r + 1, hi)) {
          out.push({ val: r, left: L, right: R });
        }
      }
    }
    return out;
  }
  return build(1, n);
}
class Solution {
    public List<TreeNode> generateTrees(int n) {
        if (n == 0) return new ArrayList<>();
        return build(1, n);
    }
    List<TreeNode> build(int lo, int hi) {
        List<TreeNode> out = new ArrayList<>();
        if (lo > hi) { out.add(null); return out; }
        for (int r = lo; r <= hi; r++)
            for (TreeNode L : build(lo, r - 1))
                for (TreeNode R : build(r + 1, hi))
                    out.add(new TreeNode(r, L, R));
        return out;
    }
}
vector<TreeNode*> build(int lo, int hi) {
    if (lo > hi) return { nullptr };
    vector<TreeNode*> out;
    for (int r = lo; r <= hi; r++)
        for (auto* L : build(lo, r - 1))
            for (auto* R : build(r + 1, hi))
                out.push_back(new TreeNode(r, L, R));
    return out;
}
vector<TreeNode*> generateTrees(int n) { return n ? build(1, n) : vector<TreeNode*>{}; }
Time: O(n · Cn) Space: O(n · Cn)