DBSCAN Time Complexity · Naive O(n²) vs O(n log n) with Spatial Indexing
DBSCAN’s time complexity depends critically on the region query implementation.
Naive Implementation
For each point, check distance to every other point → $O(n^2)$ region queries × $O(d)$ distance computation = $O(n^2 d)$. Practical for n < 10,000 on modern hardware.
Spatial Index Implementation
With a spatial index (R*-tree, kd-tree, ball tree): each region query is $O(\log n)$ on average. Total: $O(n \log n)$ with $O(n)$ for index construction. This is the standard scikit-learn implementation with algorithm='ball_tree'.
Worst Case
In high dimensions, spatial indices degrade to $O(n)$ per query (the index cannot effectively prune the search space). Total: $O(n^2)$ regardless of the index choice. This is fundamental — not an implementation limitation — and explains why DBSCAN should not be used on high-dimensional data without dimensionality reduction.
Memory
$O(n)$ for the spatial index (tree structure) + $O(n)$ for labels and core sample flags. The distance matrix is not stored explicitly (computed on-the-fly), which is the key difference from algorithms that require an $O(n^2)$ matrix.
Practical Runtimes (scikit-learn, single core)
- 10,000: 2 · <1 second
- 50,000: 2 · ~3 seconds
- 100,000: 10 · ~10 seconds
- 500,000: 10 · ~60 seconds
- 1,000,000: 2 · ~3 minutes
HDBSCAN is typically 2–5× slower than DBSCAN for the same dataset size due to the additional hierarchy construction.