创建树

  1. Construct Binary Tree from Preorder and Inorder Traversal

  2. Construct Binary Tree from Inorder and Postorder Traversal

  3. Unique Binary Search Trees

  4. Unique Binary Search Trees II

  5. Different Ways to Add Parentheses

1. Preorder + Inorder --> Binary Tree

             [1] 
           /     \ 
         [5]      [4]
        /   \       \ 
      [2]   [3]      [6] 
                    /
                  [7]
In-order: 【(2,5,3) 1 (4,7,6)】
Pre-order: 【1 (5,2,3) (4,6,7)】

key: 递归 + 传入时候, inorder + preorder对应left, right的范围

Time: O(N^2), 最坏的情况是,tree is left skewed. Example Preorder and Inorder traversals for worst case are {A, B, C, D} and {D, C, B, A}. For each level, traverse all node in in-order array, O(n), and left skewed tree has N level. Therefore, n^2 is time complexity.

pre-order的第一个永远是root, 剩下的都是left and right subtree.

所以问题转换成how to divide the rest of treenodes into right subtree and left subtree.

这个时候,就需要用Inorder的序列来确定left subtree的长度了.

可以通过在inorder里面找root的值来判断left subtree的长度.

知道长度之后,也就知道了怎么去divide了. 然后递归的时候,left subtree传入相应的preorder and inorder的范围就可以了.

2. Inorder + Postorder --> Binary Tree

key: 熟悉的配方

3. Unique Binary Search Trees

key: 数个数,用dp

有点类似permutation, 所以这是有规律的。

n = 0

n = 1
1

n = 2
   1                  2
    \                /
     2              1

n = 3
   1          3     3       2       1
    \        /     /       / \       \
     3     2      1       1   3       2
    /     /        \                   \
   2     1          2                   3

用n = 3来举例:

根节点可以为{1, 2, 3}中的任意一个。

如以1为节点,则left subtree只能有0个节点,而right subtree有2, 3两个节点。所以left/right subtree一共的combination数量为:f(0) * f(2) = 2

以2为节点,则left subtree只能为1,right subtree只能为2:f(1) * f(1) = 1

以3为节点,则left subtree有1, 2两个节点,right subtree有0个节点:f(2)*f(0) = 2

所以规律为:

f(n) = f(0) * f(n - 1) + f(1)*f(n-2) + ... + f(n-2)*f(1) + f(n-1)*f(0)

这个思路有点类似于Inorder,决定了中间的root的之后,看两边的数字有多少种组合。

4. Unique Binary Search Trees II

key: recursion + list and queue can store null object

要求生成所有的unique BST,类似combination/permutation的题目,可以递归构造。

1. 根节点可以任取min ~ max (例如min = 1, max = n),假如取定为i。

2. 则left subtree由min ~ i-1组成,假设可以有L种可能。right subtree由i+1 ~ max组成,假设有R种可能。生成所有可能的left/right subtree。

3 对于每个生成的left subtree/right subtree组合<T_left(p), T_right(q)>,p = 1...L,q = 1...R,添加上根节点i而组成一颗新树。

class Solution {

    public List<TreeNode> generateTrees(int n) {
        if (n == 0) return new LinkedList<TreeNode>();
        return build(1, n);//1...n
    }

    private List<TreeNode> build(int left, int right) {
        List<TreeNode> list = new LinkedList<TreeNode>();
        //key: list and queue can store null, size = 1
        if (left > right) {
            list.add(null);
            return list;
        }
        for (int i = left; i <= right; i++) {
            List<TreeNode> leftTree = build(left, i - 1);
            List<TreeNode> rightTree = build(i + 1, right);
            //base case: leaf node的两个list都储存了一个null
            for (int a = 0; a < leftTree.size(); a++) {
                for (int b = 0; b < rightTree.size(); b++) {
                    TreeNode root = new TreeNode(i);
                    root.left = leftTree.get(a);
                    root.right = rightTree.get(b);
                    list.add(root);
                }
            }
        }
        return list;
    }
}

Different Ways to Add Parentheses

Like a binary tree, root and all internal nodes are operators; leaves are number

map(string, List<number result>)

class Solution {
    //like a binary tree. root and all internal nodes are operator
    //leaves are num
    //construct different binary tree
    public List<Integer> diffWaysToCompute(String input) {
        Map<String, List<Integer>> memo = new HashMap<String, List<Integer>>();
        constructTree(input, memo);
        return memo.get(input);
    }

    private List<Integer> constructTree(String input, Map<String, List<Integer>> memo) {
        List<Integer> res = new LinkedList<Integer>();
        for (int i = 0; i < input.length(); i++) {
            char curr = input.charAt(i);
            if (curr == '+' || curr == '-' || curr == '*') {
                String leftPart = input.substring(0, i);
                List<Integer> left = memo.containsKey(leftPart) ? memo.get(leftPart) : constructTree(leftPart, memo);
                memo.put(leftPart, left);
                String rightPart = input.substring(i + 1);
                List<Integer> right = memo.containsKey(rightPart) ? memo.get(rightPart) : constructTree(rightPart, memo);
                memo.put(rightPart, right);
                for (int l: left) {
                    for (int r: right) {
                        if (curr == '+') res.add(l + r);
                        else if (curr == '-') res.add(l - r);
                        else res.add(l * r);
                    }
                }
            }
        }
        // base case. e.g."11"
        if (res.size() == 0) res.add(Integer.parseInt(input));
        memo.put(input, res);
        return res;
    }
}

results matching ""

    No results matching ""