给定一个整数 n,生成所有由 1 … n 为节点所组成的二叉搜索树。
示例:
输入: 3
输出:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
解释:
以上的输出对应以下 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-binary-search-trees-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析:
- 输入一个n,需要的输出为所有可能的二叉搜索树的根节点的集合。显然1-n每个点都可以成为根节点返回,那么就需要从1到n遍历往下生成树。每个点成为根节点的次数大于等于1。
- 既然要遍历生成,那么从1-n中随机抽取一个数字m进行分析如何向下生成。根据二叉搜索树的性质,抽取一个数字m把1-n划分成了1 - (m-1)和(m+1) - n两部分,而前者正好必须都在m节点的左子树上,后者必须在其右子树上。若能把上述两部分能生成的所有二叉搜索树全部生成并分别记录各自的根节点,后面则只需要由点m连接左子树和右子树再返回m根节点即可。
- 根据1,2两步分析得到的方法是分治策略,每一步针对几个连续数字,抽取一个数字,对剩下的两部分数字进行递归解决,递归直到start>end开始回溯,回溯时加入null,据上述分析start不会等于end。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<TreeNode> generateTrees(int n) {
if (n < 1) return new ArrayList<>();
return generateSubtrees(1, n);
}
public List<TreeNode> generateSubtrees(int start, int end) {
List<TreeNode> res = new ArrayList<>();
if (start > end) {
res.add(null);
return res;
}
for (int i = start; i <= end; ++i) {
List<TreeNode> left = generateSubtrees(start, i - 1);
List<TreeNode> right = generateSubtrees(i + 1, end);
for (TreeNode l : left) {
for (TreeNode r : right) {
TreeNode root = new TreeNode(i);
root.left = l;
root.right = r;
res.add(root);
}
}
}
return res;
}
}