unique Binary Tree

第一种 : 给定一个数值 n 求它能构成的不同的BST的个数:

 这类题,很像那个求斐波那契和,关键就是把状态记录

  通过一个数组 把 1 到 i 的BST数目记录 , : 范围大小相等,那么BST的数目一样,接下来就可以直接利用了!

public class Solution {
    public int numTrees(int n) {
        int[] num = new int[n + 1];
        num[0] = 1;
        
        for (int i = 1 ; i <= n ; i++) { // 1 到i构建BST
            int count = 0;
            for (int j = 1 ; j <= i ; j++) {//哪一个为根节点
                int left  = j - 1; // 左子树的节点个数
                int right = i - j; // 右子树的节点个数
                count += (num[left] * num[right]);
            }
            num[i] = count;
        }
        return num[n];
    }
}

  

第二种类型 : 要求的不是不同BST的个数,而是把每一棵BST列出来。

  这个题目,开始的时候卡在了右子树该怎么表示那块了!!

 总的来说,这个题目的思路,就是通过一个列表来存储之前数值相对应的子树,只要要表示的数值范围相同,那么子树的形状都是一样,

 比如123 和 456!!!

// 1234  那么当root = 3, left = 2  root = 4 left = 3 ,我想,用一个map把对应的范围内的树存起来,用的时候在来取
    // 比如把 12 的可能情况存起来,求123的BST,root=3的话,就直接可以用12的了?但是一个问题root = 1? 或者 123456 ,root = 3
    // 456怎么办!!这道题目的精华就在这里了!!前面那种解法是没有错的,即通过一个链表来存放各个值对应的树!但要表示456 ,相对应的
    // 就只要把123 的值+3不就等于456了吗!!!! 
     public List<TreeNode> generateTrees(int n) {
        Map<Integer , List<TreeNode>> map = new HashMap<> (); // 每个值对应的树
        List<TreeNode> l = new ArrayList<>();
        // put 0
        l.add(null);
        if(n < 1) return l;
        map.put(0,l); // 0 
        // put 1
        l = new LinkedList<TreeNode>();
        TreeNode root = new TreeNode(1);
        l.add(root);
        map.put(1, l);
        
        for(int i = 2 ; i <= n ; i++) { // 1 到 n  1234567
            List<TreeNode> list = new ArrayList<>();
            // TreeNode node = new TreeNode(i); // 加入 i = 7
            for(int j = 1 ; j <= i ; j++) { // 1到i中哪一个值为顶点
                List<TreeNode> left = map.get(j - 1); // 6 5 4 3 2 1 0
                List<TreeNode> right = map.get(i - j); //0 1 2 3 4 5 6
                for (TreeNode ln : left) {
                    for (TreeNode rn : right) {  
                        TreeNode node = new TreeNode(j); //注意这一块,你不能在上面那个for循环定义TreeNode ,或者更上层,因为这里每一个treeNode对应着的就是一颗新的树
                             node.left = ln;                  // 你如果在外层循环中定义,这不会乱套了吗。
                             node.right = copyToRight(rn , j); //右子树的节点 就需要把左子树中相同数目的子树 的 节点 + add! 
                        list.add(node);
                    }
                }
            }
            map.put(i , list);
        }
        return map.get(n);
    }
    
    // 只要节点的数目相同,那么他们子树形状都是一样,我们接下来要的就是遍历树,对每个节点 val + add
    public TreeNode copyToRight(TreeNode node , int add) {
        if(node == null) return node;
        TreeNode n = new TreeNode (node.val + add);
        n.left = copyToRight(node.left , add);
        n.right = copyToRight(node.right , add);
        return n;
    }
    
}

猜你喜欢

转载自kainever7.iteye.com/blog/2207623
今日推荐