LeetCode series of binary tree

Trees are more common computer science data structure, it will be arranged in a hierarchy node data organized together, it is a special FIG.

Generally speaking tree has the following properties:

  1. Tree usually has only a root node;
  2. In addition to the root node, all nodes have a unique parent node;
  3. Node has no children is called a leaf node;
  4. At least one sub-root node of non-called internal node;
  5. A ntree consisting of nodes having n-1sides;
  6. The child nodes parent node independent observation, the child node of the tree also has properties (subtree)

Usually start from the root node of the tree in computer science, from top to bottom depicting the hierarchy tree.


This paper describes a binary tree, because it is simple and important

Each node of the tree can only have a maximum of two children .

Typically a binary tree of nodes defined as follows, leftrepresents a left subtree root node, righta right subtree root node, vali.e., the corresponding value is.

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
复制代码

For the binary tree, which traverse generally three ways: first order, and the subsequent sequence, whose primary difference is different timings access nodes , particularly pseudo-code as follows:

def visit(node):
    << preorder actions >>
    left_val = visit(node.left)
    << inorder actions >>
    right_val = visit(node.right)
    << postorder actions >>
复制代码

Binary search tree is a special binary tree, for each node which nodehas the following properties:

  • node All values ​​are less than the left child node 
  • node All values ​​are greater than the right child node

LeetCode link

Subtree of Another Tree

Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node's descendants. The tree s could also be considered as a subtree of itself.

Sample

Given tree s:

     3
    / \
   4   5
  / \
 1   2
复制代码

Given tree t:

   4 
  / \
 1   2
复制代码

Return true, because t has the same structure and node values with a subtree of s.

Given tree s:

     3
    / \
   4   5
  / \
 1   2
    /
   0
复制代码

Given tree t:

   4
  / \
 1   2
复制代码

Return false.

answer

The effect of this problem is to give you two trees, the tree is not the first judge of the second sub-tree of the tree, the method is very straightforward: First, identify all nodes of the first tree root tree value equal to the second value, then from the set of subtrees the nodes (which may include root node) to identify a second tree node tree completely equivalent. Therefore, this is converted to the title, given two nodes, it is determined whether the same two trees. Because the binary tree recursive structure, we can easily write a recursive function to determine whether two trees congruent: in a given case of two non-empty nodes congruent left subtree, right subtree congruent, the value of the root We are equal; if at least one of the two nodes is empty, the conditions for the two congruent node must be empty.

bool isSameTree(TreeNode *p, TreeNode *q) {
    if (p && q) {
        bool leftSame = isSameTree(p->left, q->left);
        bool rightSame = isSameTree(p->right, q->right);
        return leftSame && rightSame && p->val == q->val;
    }
    return p == NULL && q == NULL;
}
复制代码

The main function mainly by using the search function to make it level.

bool isSubtree(TreeNode* s, TreeNode* t) {
    TreeNode *p;
    queue<TreeNode*> q;
    q.push(s);
    vector<TreeNode*> targets;
    while (!q.empty()) {
        p = q.front();
        q.pop();
        if (p->val == t->val)
            targets.push_back(p);
        if (p->left)
            q.push(p->left);
        if (p->right)
            q.push(p->right);
    }
    for (int i = 0; i < targets.size(); ++i) {
        if (isSameTree(t, targets[i])) {
            targets.clear();
            return true;       
        }
    }
    return false;
}
复制代码

Diameter of Binary Tree

Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.

Sample

Given a binary tree

          1
         / \
        2   3
       / \     
      4   5    
复制代码

Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].

The length of path between two nodes is represented by the number of edges between them.

answer

Briefly, this question is to find the two vertices in the tree furthest distance, and outputs the length of this distance.

At first I thought of this question, is not simply about the depth of the sub-tree is calculated separately, after summing up the results found? So my first submission is written like this:

int diameterOfBinaryTree(TreeNode *root) {
    if (root == NULL)
        return 0;
    int ld = depth(root->left), rd = depth(root->right);
    return ld + rd;
}
int depth(TreeNode *r) {
    if (r == NULL)
        return 0;
    return max(depth(r->left), depth(r->right)) + 1;
}
int max(int a, int b) {
    return a > b ? a : b;
}
复制代码

The above function, depthis used to find the root of a tree to rdepth (depth so that the leaf node 1), then the longest path is about the depth of the tree and child, but this is wrong! Because of this it implied a

Wrong assumptions

: A tree of the longest path through some of its root. Look at an example:

          1
         / 
        2   
       / \     
      4   5    
     /     \
    6       7
复制代码

As shown above, the root node through 1a path of up to 3, but the tree should be the longest path [6, 4, 2, 5, 7], should be between 4. So I changed the above code as follows, in fact, the specific algorithm is the same, only this time I traversed all the tree nodes: If the above code is to look after the root of the longest path length, the code here is all the longest path length calculated all tree nodes, and then select the maximum.

int diameterOfBinaryTree(TreeNode *root) {
    if (root == NULL)
        return 0;
    int ld = diameterOfBinaryTree(root->left), rd = diameterOfBinaryTree(root->right);
    return max(max(ld, rd), maxPath(root));
}

int maxPath(TreeNode *r) {
    if (r == NULL)
        return 0;
    int ld = depth(r->left), rd = depth(r->right);
    return ld + rd;
}

int depth(TreeNode *r) {
    if (r == NULL)
        return 0;
    return max(depth(r->left), depth(r->right)) + 1;
}
int max(int a, int b) {
    return a > b ? a : b;
}

复制代码

Unique Binary Search Trees

Given n, asked by the 1...nlook for the different nodes of a binary tree, how many?

Sample

Given n = 3, there are 5different forms of binary search tree:

1           3     3       2       1
 \         /     /       / \       \
  3      2      1       1   3       2
 /      /        \                   \
2     1           2                   3
复制代码

answer

I find this question mainly by law. So nis the number of nodes, f(n)by 1...nis the number of nodes of different forms of binary search tree.

n = 1

n = 1The answer is yes, only one form, f(1) = 1.

1
复制代码

n = 2

n = 2The situation is well understood, but when it does not appear that law f(2) = 2.

1           2 
 \         /  
  2      1    
复制代码

n = 3

The sample in Figure gave is not very clear, I arranged a little bit, from small to large size value in accordance with the root node:

1     1           2             3    3 
 \     \         / \           /    /   
  3     2       1   3        2     1     
 /       \                  /       \     
2         3               1          2     
复制代码

When the root node is 1 the number of tree form when, by the n = 2 number of determined shape;
When the root node is 2 the number of tree form when, by the n = 1 number of determined shape;
When the value of the root node 3 when the number of tree form is determined by n = 2 the number of determined shape.

Why do they say, because the root node 1, the left sub-tree will be empty, and the right subtree of 2and 3composition, that is n = 2the case; but the root is 2, the left and right subtrees of scale (ie nodes) are 1, that is n = 1the situation. Also notice when the root changes, change its size and shape of the left and right sub-tree. Finding a binary tree nature seen, the values of all the nodes is smaller than the left subtree of the root node, the values of all the nodes is greater than the right subtree of the root node, and because the range of values in a set of nodes {1, 2, ..., n}within, when the root node is determined, left and right scale sub-tree also identified. The root node is assumed i, then the size of the left subtree i - 1, right subtree scale n-i. As above, n = 3, i = 1when the left and right subtrees of size 0 and 2, respectively, and so on.

Can we conclude it:

f(1) = 1
f(2) = 2
f(3) = f(2) + f(1) + f(2)
复制代码

The best look at n = 4the situation.

n = 4

Due to this situation accounted for more space, so I will be expressed in more abstract way, so that g(n)represents a nform different nodes of a binary tree collection , there are:

1           2           3           4   
 \         / \         / \         /    
  g(3)   g(1) g(2)   g(2) g(1)   g(3)   

复制代码

There can be seen a very delicate place here (the root node is 2 or 3), is the form of a combination of left and right subtrees of the binary tree, form left subtree and right subtree are independent, and therefore a fixed value of the root node , the total number of the number of the two should form a product form .

f(1) = 1
f(2) = f(1) * f(0) + f(0) * f(1)
f(3) = f(2) * f(0) + f(1) * f(1) + f(0) * f(2)
f(4) = f(3) * f(0) + f(2) * f(1) + f(1) * f(2) + f(0) * f(3)
复制代码

We can see from the above equation, in order to calculate f(4), need to repeat the calculation 2times f(1)、f(2)和f(3), and f(3)have to repeat the call f(1)和f(2), when nrelatively large, this is very time-consuming calculation, the calculation results in the calculation to be cached.

To facilitate the programming, the definition f(0) = 1, there are:

class Solution {
public:
    /**
     * @paramn n: An integer
     * @return: An integer
     */
    int cache[1000];
    Solution() {
        for (int i = 0; i < 1000; ++i)
            cache[i] = -1;
    }
    int numTrees(int n) {
        // write your code here
        if (cache[n] != -1)
            return cache[n];
        if (n == 0)
            return cache[n] = 1;
        if (n == 1 || n == 2)
            return cache[n] = n;
        int r = 0;
        for (int i = 1; i <= n; ++i)
            r += numTrees(n - i) * numTrees(i - 1);
        return cache[n] = r;
    }
};复制代码


Reproduced in: https: //juejin.im/post/5d07cf61518825684b589289

Guess you like

Origin blog.csdn.net/weixin_34245749/article/details/93167936