原题链接:https://leetcode.com/problems/unique-binary-search-trees-ii/
1. 题目介绍
Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1 … n.
给出一个整数n,返回从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]
]
2. 解题思路
这道题和 96. Unique Binary Search Trees 是同一道题,但是 96. Unique Binary Search Trees 只需要返回二叉树的个数,而本题则是返回二叉树本身。
动态规划法
注:本思路根据 https://blog.csdn.net/chilseasai/article/details/50083201 改写而来,感兴趣的读者可以直接去看原文。
解决本题可以使用动态规划的思路,将问题逐步分解。为了求出所有不同的二叉树,需要交替按照下面两步进行:
1 . 在一个范围内选取一个结点作为根。
2 . 每选取一个结点作为根,就把树切分成左右两个子树,直至该结点左右子树为空。
一开始,这个范围是(1,n),接下来如果选取 i 作为根节点,那么这个 i 的左子树的范围就是(1,i-1),左子树在(1,i-1)中再选一个节点作为根;右子树的范围就是(i+1,n),右子树在(i+1,n)中选一个节点作为右子树的根。依次细分下去
于是,这是一个可以划分成子问题求解的题目,所以可以使用动态规划求解。
但具体对于本题来说,采取的是自底向上的求解过程。
1 . 选出根结点后应该先分别求解该根的左右子树集合,也就是根的左子树有若干种,它们组成左子树集合,根的右子树有若干种,它们组成右子树集合。
2 . 然后将左右子树相互配对,每一个左子树都与所有右子树匹配,每一个右子树都与所有的左子树匹配。然后将两个子树插在根结点上。
3 . 最后,把根结点放入总的List结果中。
具体实现可以参考以下代码:
/**
* 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){//测试样例中有一个n = 0
return new ArrayList<>();
}
return helper(1,n);
}
public List<TreeNode> helper(int begin, int end){
List<TreeNode> ans = new ArrayList<>();
if(begin > end){
ans.add(null);//添加null而不是直接返回,可以方便处理子树为空的情况
return ans;
}
for(int i =begin ; i<=end ; i++){
//确定根节点是i后,求所有左子树集合和右子树集合
List<TreeNode> leftChild = helper(begin, i-1);
List<TreeNode> rightChild = helper( i+1 , end);
//从取出集合中的左右子树一一配对
for(int j = 0; j<leftChild.size();j++){
for(int k = 0;k<rightChild.size();k++){
TreeNode root = new TreeNode(i);
root.left = leftChild.get(j);
root.right = rightChild.get(k);
ans.add(root);
}
}
}
return ans;
}
}