96. Unique Binary Search Trees1和2

/*
        这道题的关键是:动态表尽量的选取,知道二叉搜索树中左子树的点都比根节点小,右子树的点都比根节点大
        所以当i为根节点,左子树有i-1个点,右子树有n-i个点,左右子树就可以开始递归构建,过程和一开始的过程是一样的,
        而左右子树的特征中可以知道的就是点的个数,所以用点的个数作为动态变量就很好。
        这样就给我们提供了一个思路:动态规划和树结合的题,由于子问题就是左右树,所以动态变量的选取基本就是考虑题目给出的信息
        中,可以从根节点得到左右子树的哪些特征,用这个特征作为动态变量。

        二叉搜索树中,都是左子树的点小于根节点,右子树的点大于根节点,对于所有子树都是这样。
        用dp[i]表示有i个数的时候能组成多少树

        dp[i] = dp[0]*dp[i-1]+ ...+ dp[i-1]*dp[0]
        等号右边分别代表1到i分别是根节点的情况
         */
        int[] dp = new int[n+1];
        dp[0] = 1;//当没有节点时,就只有一种情况
        for (int i = 1; i < n+1; i++) {
            for (int j = 0; j < i; j++) {
                dp[i] += dp[j] * dp[i-j-1];
            }
        }
        return dp[n];
 1  public List<TreeNode> generateTrees(int n) {
 2         /*
 3         从i到n依次选取做为根节点,生成一棵树.根节点为i的这个过程我们叫做function(i),则function(i)中左子树就是从1到i-1的
 4         生成过程,右子树就是从i+1到n的过程,递归function就行,然后对左右子树就行全匹配就行
 5          */
 6         if (n < 1)
 7             return new ArrayList<TreeNode>();
 8         return build(1, n);
 9     }
10 
11     public List<TreeNode> build(int start, int end) {
12         List<TreeNode> res = new ArrayList<>();
13         if (start > end)
14         {
15             res.add(null);
16             return res;
17         }
18         for (int i = start; i <= end; i++) {
19             List<TreeNode> left = build(start, i - 1);
20             List<TreeNode> right = build(i + 1, end);
21 
22             for (TreeNode lt :
23                     left) {
24                 for (TreeNode rt :
25                         right) {
26                     //由于每次组合都形成一个新的树,所以新建树应该是在这里
27                     TreeNode root = new TreeNode(i);
28                     root.left = lt;
29                     root.right = rt;
30                     //注意添加的位置,每组合一个左右子树就会形成一种情况
31                     res.add(root);
32                 }
33             }
34 
35         }
36         return res;
37     }
原文地址:https://www.cnblogs.com/stAr-1/p/7922877.html