动态规划(不同的二叉搜索树||)
考虑 [] 的所有解
null
考虑 [ 1 ] 的所有解
1
考虑 [ 1 2 ] 的所有解
2
/
1
1
\
2
考虑 [ 1 2 3 ] 的所有解
3
/
2
/
1
2
/ \
1 3
3
/
1
\
2
1
\
3
/
2
1
\
2
\
3
思路 :当我们增加一个大于之前的数字时,新增的数字出现的位置只能是根节点或根节点的右孩子、右孩子的右孩子等等。接着,新数字所在位置原来的子树,改为当前插入数字的左孩子即可(因为他是最大的)。
对于下边的解
2
/
1
然后增加 3
1.把 3 放到根节点
3
/
2
/
1
2. 把 3 放到根节点的右孩子
2
/ \
1 3
对于下边的解
1
\
2
然后增加 3
1.把 3 放到根节点
3
/
1
\
2
2. 把 3 放到根节点的右孩子,原来的子树作为 3 的左孩子
1
\
3
/
2
3. 把 3 放到根节点的右孩子的右孩子
1
\
2
\
3
code
public List<TreeNode> generateTrees(int n){
//pre list保存上一次的所有解
List<TreeNode> pre = new ArrayList<TreeNode>();
if(n == 0){
return pre;
}
pre.add(null);
for(int i=1;i<=n;i++){
//cur计算当前的所有解
List<TreeNode> cur = new ArrayList<TreeNode>();
//遍历之前的所有解
for (TreeNode root : pre){
//插入到根节点
TreeNode insert = new TreeNode(i);
insert.left = root;
cur.add(insert);
//插入到右孩子,右孩子的右孩子...最多找n次孩子
for(int j = 0;j <= n;j++){
TreeNode root_copy = treeCopy(root);//复制当前的树
TreeNode right = root_copy;//找到要插入右孩子的位置
int k = 0;
//遍历j次找到右孩子
for(;k < j;k++){
if(right == null){
break;
}
right = right.right;
}
//到达null提前结束
if(right == null){
break;
}
//保存当前右孩子的位置的子树作为插入节点的左孩子
TreeNode rightTree = right.right;
insert = new TreeNode(i);
right.right = insert;//右孩子是插入的节点
insert.left = rightTree;//插入节点的左孩子更新为插入位置之前的子树
//加入结果中
cur.add(root_copy);
}
}
pre = cur;
}
return pre;
}
//复制子树
private TreeNode treeCopy(TreeNode root){
if(root == null){
return root;
}
TreeNode newRoot = new TreeNode(root.val);
newRoot.left = treeCopy(root.left);
newRoot.right = treeCopy(root.right);
return newRoot;
}