题目来源:https://leetcode.com/problems/unique-binary-search-trees-ii/
问题描述
95. Unique Binary Search Trees II
Medium
Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ... n.
Example:
Input: 3
Output:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
Explanation:
The above output corresponds to the 5 unique BST's shown below:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
------------------------------------------------------------
题意
给定整数n,求所有以1~n为节点值的二叉搜索树组成的数列(给定二叉搜索树的顺序为“左子树<根节点<右子树”)
------------------------------------------------------------
思路
引理:二叉搜索树的子树各节点的值是连续的。
引理的证明:反证法。假设存在一个子树的值不连续,不妨设该子树是根节点的左子树,则缺失的值必定小于左子树的最右节点的值,而该缺失的值在左子树的根节点或左子树的根节点的右子树中,即左子树的根节点或左子树的根节点的右子树中存在一个节点,其值小于左子树中的最右节点,这与二叉搜索树定义的“左子树<根节点<右子树”的搜索顺序矛盾。若该子树是根节点的右子树则同理可证。证毕。
根据引理,我们可以用递归的方式来构造。在1~n中遍历根节点的取值i,然后构造左子树1~(i-1),再构造右子树(i+1)~n.
具体实现上,要注意数组中的元素是持有的对象的引用,因此每个元素要new一个根节点出来,不能在原来的根节点上修改,否则会同步修改数组中的既有元素。
------------------------------------------------------------
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
/**
For debugging
*/
private void printNode(TreeNode node)
{
if (node == null)
{
System.out.print("null");
return;
}
System.out.print(node.val + ", ");
printNode(node.left);
printNode(node.right);
}
private List<TreeNode> recuGen(int begin, int end)
{
if (begin > end)
{
return new LinkedList<TreeNode>(){
{
add(null);
}
};
}
if (begin == end)
{
return new LinkedList<TreeNode>(){
{
add(new TreeNode(begin));
}
};
}
List<TreeNode> ret = new LinkedList<TreeNode>();
for (int i = begin; i <= end; i++)
{
List<TreeNode> subL = recuGen(begin, i - 1);
List<TreeNode> subR = recuGen(i + 1, end);
for (TreeNode subl: subL)
{
for (TreeNode subr: subR)
{
TreeNode root = new TreeNode(i); // must new {@code root} in the inner iteration, because list only hosts the reference of the {@code root} object
root.left = subl;
root.right = subr;
ret.add(root);
}
}
}
return ret;
}
public List<TreeNode> generateTrees(int n) {
return n != 0 ? recuGen(1, n): Collections.emptyList();
}
}