Q1 (easy): Given an array where elements are sorted in ascending order, convert it to a height balanced BST, where the depth of the two subtrees of every node never differ by more than 1.
Q2 (medium): How about a sorted slist?
I feel this “easy” problem should be medium. Perhaps there are elegant solutions.
I need not care about the payloads in the array. I can assume each payload equals the subscript.
There are many balanced BSTs. Just need to find one
— idea 1: construct an sequence of positions to probe the array. Each probed value would be added to the tree. The tree would grow level by level, starting from root.
The sequence is similar to a BFT. This way of tree building ensures
- only the lowest branch nodes can be incomplete.
- at all branch levels, node count is 2^L
I think it’s challenging to ensure we don’t miss any position.
Observation — a segment of size 7 or shorter is easy to convert into a balanced subtree, to be attached to the final BST.
When a subarray (between two probed positions) is recognized as such a segment we can pass it to a simple routine that returns the “root” of the subtree, and attach it to the final BST. This design is visual and a clean solution to the “end-of-iteration” challenge.
The alternative solution would iterate until the segment sizes become 0 or 1. I think the coding interviewer probably prefers this solution as it is shorter but I prefer mine.
— idea 2
Note a complete binary tree can be efficiently represented as an array indexed from one (not zero).
— Idea 3 (elegant) dummy payload — For the slist without using extra storage, I can construct a balanced tree with dummy payload, and fill in the payload via in-order walk
All tree levels are full except the leaf level — guarantees height-balanced. We can leave the right-most leaf nodes missing — a so-called “complete” binary tree. This way the tree-construction is simple — build level by level, left to right.
— idea 4 STL insert() — For the slist, we can achieve O(N) by inserting each element in constant time using STL insert() with hint
— For the slist without using an array, I can get the size SZ. (then divide it by 2 until it becomes 7,6,5 or 4.) Find the highest 3 bits (of SZ) which represent an int t, where 4 <= t <= 7. Suppose that value is 6.
We are lucky if every leaf-subtree can be size 6. Then we just construct eight (or 4, or 16 …) such leaf-subtrees
If SZ doesn’t give us such a nice scenario, then some leaf-subtrees would be size 5. Then my solution is to construct eight (or 4, or 16 …) leaf-trees of type AAAAA (size 6) then BBB (size 5).
Lucky or unlucky, the remaining nodes must number 2^K-1 like 3,7,15,31 etc. We then construct the next level.
–For the slist without using an array, I can propose a O(N logN) recursive solution:
locate the middle node of slist. Construct a tree with root node populated with this value.
Then cut the left segment as a separated slist1, compute its length as sz1. node1 = f(slist1,sz1); set node1 as the left child of root.
Repeat it for the right segment
return the root