1 问题
问题描述:
Given an integer n
, return all the structurally unique BST’s (binary search trees), which has exactly n
nodes of unique values from 1
to n
. Return the answer in any order.
Example 1:
Input: n = 3
Output: [[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
Example 2:
Input: n = 1
Output: [[1]]
Constraints:
- 1 <= n <= 8
TreeNode
结构如下:
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
2 问题分析与求解
这题是唯一BST个数 的延伸.
看示例给出的结果:
Input: n = 3
Output: [[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
虽然这里使用 内部数组 表示的输出, 但实际上我们输出的数组的元素应该是 TreeNode
结构, 比如:
Output: [TreeNode1, TreeNode2, TreeNode3, TreeNode4, TreeNode5]
这个题我思考许久, 没有做出来==…
下面参考别人的一种解法, 然后总结一下解题思路:
public List<TreeNode> generateTrees(int n) {
if (n < 0)
return null;
return generateTrees(1, n);
}
private List<TreeNode> generateTrees(int begin, int end) {
ArrayList<TreeNode> results = new ArrayList<TreeNode>();
if (begin > end) {
results.add(null);
return results;
}
for (int i = begin; i <= end; i++) {
List<TreeNode> left = generateTrees(begin, i - 1);
List<TreeNode> right = generateTrees(i + 1, end);
for (TreeNode leftNode : left) {
for (TreeNode rightNode : right) {
TreeNode root = new TreeNode(i);
root.left = leftNode;
root.right = rightNode;
results.add(root);
}
}
}
return results;
}
这种建树问题一般来说都是用递归来解,这道题也不例外,划分左右子树,递归构造.
开始, 将区间 [1, n]
当作一个整体(begin=1
, end=n
), 然后需要将其中的每个数字(从 1
到 n
)都当作根结点遍历, 遍历每个结点都划分开了 左右两个子区间, 然后对两个子区间分别调用 递归函数, 会得到 两个结点数组, 接下来从这两个数组中每次各取一个结点, 当作当前根结点的左右子结点, 然后将根结点加入结果 results
数组中即可
如果以 i
为根节点, 那么其 左子树由[1, i - 1]
构成, 右子树由 [i + 1, n]
构成.
n=3
时, 我画出了递归调用过程:
3 总结
构建树需要考虑递归:
- 递归退出条件需要考虑清楚.
- 递归过程中结果如何存储.
可以先在纸上画一下, 本来没有思路, 可能画着画着就有思路了.