[Title] algorithm recursion depth of a binary tree

The depth of the binary tree algorithm, is a binary tree algorithm based on the comparison. Corresponds LeetCode 104 questions .

Then you will find some algorithm behind LeetCode questions need to use variations of this algorithm, such as the first 110 questions, 543 questions. These two questions, if you know the depth of recursion binary tree algorithm, it is easy to make out.

About binary tree of knowledge, I can see this article: a simple analysis of summary data structure] tree (js achieve attached)

Title Description

Given a binary tree to find its maximum depth.

The depth of the binary tree is the root node to the nodes on the longest path farthest leaf node.

Description: leaf node is a node has no child nodes.

Example:
given binary tree [3,9,20, null, null, 15,7 ],

    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3 。

Note that the binary tree by a chain storage method storage, instead of an array.

1. What is recursion

Prior to problem-solving, we first understand what is recursive (if you already know, skip directly to this section).

Then begin Long (wang) chant (ba) textbook (nian) content (jing).

Recursively divided into "delivery" and "go." "Delivery" is passed into the "return" is a function of executing the child solves a problem. Recursive achieved by constantly the problem into sub-problems, and by addressing sub-problems, and ultimately solve the original problem.

Core recursive recursive formula that, when we analyze the recursive formula, in fact recursive problem will be solved. Recursion is a widely used programming techniques, it is used by a lot of places, such as depth-first traversal (this question will use this), before and after the binary tree preorder.

Recursive need to meet three conditions:

  1. It can be decomposed into a plurality of sub-problems;
  2. In addition to the size of different data sub-problem solving thinking the same;
  3. There is a recursive termination condition.

Recursive feature of the code is relatively simple, although in most cases you have each recursive process is relatively difficult to understand, because it does not conform to the human habit of thinking, but in fact you do not have to really understand, you just know that B and C are resolved after, you can deduce the line a, B and C need to consider is how to solve the problem by child (because both the front and the same!).

Second, if too deep recursion, it can lead to memory exhaustion. Because the recursive call when you want to save a lot of records, it will maintain a call stack, when the stack is too large to exceed the available memory space, memory overflow occurs, we call stack overflow . There are four kinds of solutions the following:

  1. After more than a certain depth of recursive calls, direct error, no recursion. How much depth in the end to an overflow occurs, and can not be calculated, the other error also causes the program can not continue to run down, so this program can prevent memory overflow While it is true, and it seems no use.
  2. Cache double counting. Recursion might have called repeatedly had to solve f (k) results, in this case, it is necessary to f (k) cache, usually a hash table to cache (js can be achieved by an object). When we execute f (k) a second time, you can get directly from the cache.
  3. Into a non-recursive code. In fact, the wording was changed to circulation. The cycle is essentially a modified wording is recursive, but we realized manually recursion stack it. Written code implementation cycle will be more complex than the recursive, but also elegant enough.
  4. Tail recursion. Uses a tail call optimization technology, operating environment need to see whether this optimization. In the case of support tail call optimization, if function A final step calls another function B, it enters B, it does not call record A (internal variables such as number of A's) reservations, so you do not have a very long call stack and causes a stack overflow.


Speaking of recursion, it must mention the subject of a classic recursive, that is, "the problem climbing stairs", corresponding to the first 70 questions LeetCode .

Description of the problem climbing stairs is: Suppose you are climbing stairs. We need n (a positive integer) order you to get to the roof. Every time you can climb one or two steps. How many different ways can climb to the roof of it?

First, you can list the n = 1, n = 2 ... the walk, try to find out the law.

Rank Hashiho Take the total number of law
1 1 1
2 1 + 1,2 2
3 1 + 2, 1 + 1 + 1, 2 + 1 3

Here we can find some regular. That's come to the third stage of the walk is 2 and higher order and. Why is this so? We will find the essence through the phenomenon, essentially, to come to the n-th order, we must first go to the n-1 order, and then climb to a higher level, or to come to n - 2 bands, then climb two a higher level.

So we get such a recursive formula:f(n) = f(n-1) + f(n - 2)

Recursive writing:

var climbStairs = function(n) {
    let map = {};
    function f(n) {
        if (n < 3)  return n;
        if (map[n]) return map[n];
        
        let r =  f(n-1) + f(n - 2);
        map[n] = r;
        return r;
    }
    return f(n)

Since f (n) = f (n-1) + f (n-2). Where f (n-1), and (n-2) + f (n-3) is given by f. Where f (n-2) is performed twice, so we need to cache results f (n-2) to a map object, to reduce computation time.

Cycle wording:

var climbStairs = function(n) {
    if (n < 3) return n;

    let step1 = 1,  // 上上一步
        step2 = 2;  // 上一步

    let tmp;
    for (let i = 3; i <= n; i++) {
        tmp = step2;
        step2 = step1 + step2;
        step1 = tmp;
    }
    return step2;

};

2. Analysis

Finished recursion, we have to analyze the subject of it.

First we try to find a recursive rule. First, we know that, in addition to the leaf node, all nodes in the binary tree will have about sub-tree. So if we know about child depth of the tree, find the maximum value between the two, then add one, not that the depth of the binary tree do? Next to the leaf node to the root of the height of the binary tree is one, we can pass this as the end condition of recursion.

3. code implementation

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
    function f(node) {
        if (!node) return 0;
        return Math.max(f(node.left), f(node.right)) + 1;
    }
    return f(root);
};

Here used depth-first traversal, will go from the root to leaf nodes along the binary tree. Further, because there is no double counting, it is not necessary to cache results. There is, because there is no extra variables you want to save, you can write directly to the maxDepth function recursive function.

4. Extension: How to get the array to store the binary tree depth?

How about binary array storage (sequential storage method), there is not mentioned, please see related article I mentioned earlier.

Seeking a binary tree of depth of the array representation can be seen as seeking a depth corresponding to a complete binary tree .

Before that, let's look at how to find a node number n of full binary tree of depth k.

Depth k The number n
1 1
2 3 (=1+2)
3 7 (=1+2+4)
4 15 (=1+2+4+8)

Obviously law, formulated by simply summing geometric series, we obtain k = Math.log2(n+1)where k is the depth, the number of nodes is n-full binary tree. Then for a complete binary tree, it will be rounded up to k: k = Math.ceil( Math.log2(n+1) ).

So for the length of a sequence is stored in the storage method of the n binary tree of height k:

k = Math.ceil( Math.log2(n+1) )

(Note that there is an array of storage node from zero.)

reference

  1. Ruan Yifeng's blog - tail call optimization
  2. US Data Structures and Algorithms of: 10 | recursion: How to find three lines of code "Final Recommended"?

Guess you like

Origin blog.csdn.net/weixin_34082695/article/details/90937019