The problem:
Given n, generate all structurally unique BST's (binary search trees) that store values 1...n.
My analysis:
The problem is easy at some extent, but it is different from the problem before, which would not include many possible answers at a certain recursion step.
The recursion:
1. For a certain set of elements, let's say 1, 2, 3, 4, 5, 6, 7 (n=7)
we could choose any element from them as the root.
for (int node_index = 1, node_index <= 7; node_index++)
2. Once we have chosen an element, we divide the elements into left-sub tree's and right-sub tree's elements.
If we choosen 4 as root. Then,
left-sub tree's elements: 1, 2, 3
right-sub tree's elements: 5, 6, 7
3. We use left-sub tree's elements to construct left-sub trees(could be many forms).And the same way to construct right-sub trees(could be many forms).
4. we construct the tree by selecting one left-sub tree from left-sub trees's set and one right-sub tree from right-sub trees' set.
5. return all possible trees constructed from the array.
The idea behind this problem is meaningful and powerful. It requires some very useful skills, including:
1. how to write a recursive program, which need to explore many possible rountines, and could produce a set of answers.
1.1 how to store and pass those answers?
For a certain array of nodes, we could new a ArrayList<TreeNode> for recording all possible binary trees. When can ret the reference of the ArrayList to the higher level.
1.2 how to use those answers at high-level recursion?
We could use a for loop over the list the extract each tree individually.
for(int i = 0; i < left.size(); i++) { .....left_tree = left_tree_list.get(i) .....}
2. how to define the proper base case?
we could use "low > high" as checking condition, to test if we have reached over the last-level's node.
but at this place, we need to use a little skillful way to manipulate on the return value.
we could not directly return null pointer, but we should add null pointer into the ArrayList. Cause at each recursion, we follow the routine of getting trees from the list. Then the higher-level reursion would possible to use this "null" as pointer for its sub tree.
if (low > high) {
ret.add(null); // we would use list.get(0) to use it at higher level recursion.
return ret;
}
My solution:
public class Solution { public List<TreeNode> generateTrees(int n) { return helper(1, n); } private ArrayList<TreeNode> helper(int low, int high) { ArrayList<TreeNode> ret = new ArrayList<TreeNode> ();//a record list all possible trees. if (low > high) {//this is a common checking condition! reach the bottom! ret.add(null); return ret; } for (int node_index = low; node_index <= high; node_index ++) { ArrayList<TreeNode> left = helper(low, node_index - 1); ArrayList<TreeNode> right = helper(node_index + 1, high); for (int i = 0; i < left.size(); i++) { //for all combinations of possible sub-left and sub-right trees for (int j = 0; j < right.size(); j++) { TreeNode root = new TreeNode(node_index); root.left = left.get(i); root.right = right.get(j); ret.add(root); } } } return ret; } }