Binary Search Trees · 9 of 22
Convert Binary tree into BST
Keep the exact shape of a tree but move the numbers around so it becomes a sorted tree, by pouring the sorted numbers back in left-to-right order.
- Simple way
- time O(n^2)
room O(n) - Clever way
- time O(n log n)
room O(n)
The problem, simply
You get a binary tree with numbers in no special order. Change it into a binary search tree (BST): at every spot, smaller numbers on the left side, bigger on the right side.
The catch: the shape must stay exactly the same. You may not move any branch. You may only change which number sits in which spot.
A story to remember it
Picture it
Same shape, new numbers. Read each tree left, me, right. The old one gives 8, 2, 4, 10, 7. The new one gives 2, 4, 7, 8, 10, which is sorted, so it is a BST.
- done
Examples
The classic
- In
[10, 2, 7, 8, 4]- Out
[8, 4, 10, 2, 7]
Sorted numbers are 2, 4, 7, 8, 10. The cups in left, me, right order are: bottom left, left middle, bottom right of the left side, top, right. They get 2, 4, 7, 8, 10.
Three in a row
- In
[1, 2, 3]- Out
[2, 1, 3]
Left-to-right cup order is left child, top, right child. They get 1, 2, 3.
A stick going left
- In
[1, 2, null, 3]- Out
[3, 2, null, 1]
The leftmost cup is at the bottom, so it gets the smallest number. The top gets the biggest.
One spot
- In
[5]- Out
[5]
Already a BST.
Way 1: the simple way
Take the eggs out, but do not sort them. Visit the cups left to right, and for each cup search the whole pile for the smallest egg left, take it out and put it in.
- Collect every number into a list.
- Visit the spots in left, me, right order.
- At each spot, scan the list for the smallest number, remove it, and write it into the spot.
import java.util.*;
class Solution {
public TreeNode binaryTreeToBST(TreeNode root) {
List<Integer> pile = new ArrayList<>();
collect(root, pile);
fill(root, pile);
return root;
}
private void collect(TreeNode node, List<Integer> pile) {
if (node == null) return;
pile.add(node.val);
collect(node.left, pile);
collect(node.right, pile);
}
private void fill(TreeNode node, List<Integer> pile) {
if (node == null) return;
fill(node.left, pile);
int best = 0;
for (int i = 1; i < pile.size(); i++) { // find the smallest egg left
if (pile.get(i) < pile.get(best)) best = i;
}
node.val = pile.remove(best);
fill(node.right, pile);
}
}How long it takes: each of the n spots scans up to n numbers, O(n^2). Extra room: the pile, O(n).
Way 2: the clever way
Sort the eggs once, then pour them back.
- Collect every number into an array.
- Sort the array.
- Visit the spots in left, me, right order with a finger
kon the sorted array. Each spot getssorted[k], thenkmoves forward.
Why it works: in a BST, reading left, me, right always gives sorted order. We fill the spots in that reading order with sorted numbers, so the reading comes out sorted, so it is a BST.
Pour sorted numbers back in reading order
01 / 08
Take the numbers out of the tree: 10, 2, 7, 8, 4.
- seen
- done
- answer
- just added
- ignored
import java.util.*;
class Solution {
private int k;
public TreeNode binaryTreeToBST(TreeNode root) {
List<Integer> vals = new ArrayList<>();
collect(root, vals);
Collections.sort(vals); // line the eggs up
k = 0;
fill(root, vals); // put them back left to right
return root;
}
private void collect(TreeNode node, List<Integer> vals) {
if (node == null) return;
vals.add(node.val);
collect(node.left, vals);
collect(node.right, vals);
}
private void fill(TreeNode node, List<Integer> vals) {
if (node == null) return;
fill(node.left, vals);
node.val = vals.get(k++); // the next smallest egg
fill(node.right, vals);
}
}How long it takes: sorting is O(n log n), the two walks are O(n), so O(n log n). Extra room: the list, O(n), plus O(h) for the recursion.
Watch out for
- Filling in "me, left, right" order. Only left, me, right gives a BST.
- Using a
TreeSetto sort. It drops repeated numbers, and then you run out of eggs. Use a list and sort it. - Keeping
kas a parameter instead of a field. Each call would get its own copy and the numbers repeat.
What interviewers ask next
- Fewest swaps to turn the tree into a BST, keeping the shape. Write the numbers in reading order, then it becomes "fewest swaps to sort an array": count the cycles of the sorting permutation.
O(n log n). - Can you avoid the extra list? Turn the tree into a sorted linked list in place, then refill. In an interview,
O(n)extra room is usually fine. - What if the tree is a complete tree stored in an array? Same idea: the reading order of array positions is fixed, so fill those positions with the sorted numbers.
- Is the result balanced? Only if the original shape was. The shape is not allowed to change.
Remember this
Grown-up words: the cups are nodes, reading left, me, right is an inorder traversal, lining up the eggs is sorting, and keeping the carton is preserving the tree structure.