Split a binary search Tree
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Splitting a binary search tree means partitioning it into two valid BSTs around a pivot value. One resulting tree contains all keys less than or equal to the pivot, and the other contains all keys greater than the pivot.
The Core Recursive Idea
The BST property makes the split efficient because every comparison tells you which entire side of the tree belongs to which result.
Suppose you want to split around k:
- if
root.val <= k, then the root belongs in the left result tree - only the root's right subtree might still contain nodes that must be split
- if
root.val > k, then the root belongs in the right result tree - only the root's left subtree might still contain nodes that must be split
That leads to a natural recursive algorithm that returns two roots.
A Runnable Python Implementation
Here is a clean implementation that preserves the BST structure by rewiring child pointers during the recursion:
The important part is the pointer update after the recursive call:
- when
root.val <= k, the left side of the split coming fromroot.rightremains attached toroot.right - the right side of that split becomes the separate greater-than tree
- when
root.val > k, the logic mirrors on the left subtree
This is easier to understand if you think in terms of "keep the part that still matches the root, detach the part that no longer does."
Why the Algorithm Works
Take the root.val <= k case. Every value in root.left is already less than or equal to root.val, so it also belongs in the left result tree. The only uncertainty is in root.right, because some nodes there may still be less than or equal to k while others may be greater.
After splitting root.right, you receive:
- a subtree whose values are still less than or equal to
k - a subtree whose values are greater than
k
Attach the first one back to root.right, and return the second one as the right result tree.
The root.val > k case is the symmetric mirror image. By induction on subtree size, both returned trees remain valid BSTs.
Example Walkthrough
Consider this tree and split it at k = 4:
The result should be:
- left tree with
2,3, and4 - right tree with
5,8, and10
When the recursion starts at 5, the root is greater than 4, so 5 must belong to the right result. The algorithm then splits the left subtree rooted at 3. Since 3 <= 4, that node belongs to the left result, and only its right subtree needs further splitting. That eventually isolates 4 into the left result and reconnects the rest correctly.
The algorithm never scans irrelevant branches because the BST ordering already tells it where the uncertainty lives.
Complexity and Practical Uses
The running time is O(h), where h is the height of the tree, because the recursion follows one path down the tree and rewires pointers on the way back. In a balanced BST that is O(log n). In the worst case of a completely skewed tree, it becomes O(n).
This operation is useful in:
- treaps and other split-merge trees
- range query data structures
- persistent tree variants
- problems that need to partition keys efficiently
Even if you are not building an advanced balanced tree, split is a good example of how much work BST ordering can eliminate when you use it directly.
Common Pitfalls
The most common mistake is forgetting to reattach the subtree returned by the recursive call. If you split root.right and fail to assign the left part back into root.right, you lose nodes.
Another mistake is being inconsistent about the pivot rule. Decide whether nodes equal to k belong in the left or right result and implement that rule consistently. The code above uses "less than or equal to k" on the left side.
Developers also sometimes try to rebuild both trees from scratch, which is unnecessary. The recursive split works by reusing existing nodes and changing only a few pointers.
Summary
- Splitting a BST uses the ordering invariant to partition nodes around a pivot efficiently.
- The recursive algorithm returns two roots: one for keys less than or equal to
k, and one for keys greater thank. - Only one subtree needs recursive splitting at each step.
- Rewire child pointers carefully so nodes stay attached to the correct result tree.
- The time complexity is
O(h), which isO(log n)for balanced trees.
Related reading
- Split a list of numbers into n chunks such that the chunks have close to equal sums and keep the original order
- Split a string into pieces of max length X - split only at spaces
- Split array into chunks
- Split resize algorithm into two passes
- Split a List into smaller lists of N size
- Split a python list into other sublists i.e smaller lists
- Split vector into balanced list balancing sum of list elements
- Splitting a list into N parts of approximately equal length

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.