头图

Traversal problem

2020.11.02

No.94 In-order traversal of binary tree

Given a binary tree, return its in-order traversal.

Example:

Input: [1,null,2,3]
  1
   \
    2
   /
  3

Output: [1,3,2]
Advanced: The recursive algorithm is very simple, can you do it through an iterative algorithm?

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-tree-inorder-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=94 lang=javascript
 *
 * [94] 二叉树的中序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    let r = [];
    // 递归函数
    const recurse = root => {
        // 递归终止条件
        if(!root) return;
        // 先遍历左子树
        recurse(root.left);
        // 遇到终止条件,此时的val是符合终止条件的值
        r.push(root.val);
        // 再遍历右子树
        recurse(root.right);
    };
    recurse(root);
    return r;
};
Option II:
/*
 * @lc app=leetcode.cn id=94 lang=javascript
 *
 * [94] 二叉树的中序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    const res = [];
    const stk = [];
    while (root || stk.length) {
        while (root) {
            stk.push(root);
            root = root.left;
        }
        root = stk.pop();
        res.push(root.val);
        root = root.right;
    }
    return res;
};
third solution:
/*
 * @lc app=leetcode.cn id=94 lang=javascript
 *
 * [94] 二叉树的中序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
    const res = [];
    let predecessor = null;

    while (root) {
        if (root.left) {
            // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
            predecessor = root.left;
            while (predecessor.right && predecessor.right !== root) {
                predecessor = predecessor.right;
            }

            // 让 predecessor 的右指针指向 root,继续遍历左子树
            if (!predecessor.right) {
                predecessor.right = root;
                root = root.left;
            }
            // 说明左子树已经访问完了,我们需要断开链接
            else {
                res.push(root.val);
                predecessor.right = null;
                root = root.right;
            }
        }
        // 如果没有左孩子,则直接访问右孩子
        else {
            res.push(root.val);
            root = root.right;
        }
    }

    return res;
};
Option Four:
/*
 * @lc app=leetcode.cn id=94 lang=javascript
 *
 * [94] 二叉树的中序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function(root) {
  if (root) {
    return [...inorderTraversal(root.left), root.val, ...inorderTraversal(root.right)]
  } else {
    return []
  }
}

There are four solutions: 1. Use recursion to achieve traversal, and deal with the termination conditions of recursion, which is equivalent to an implicit stack application; 2. Use the stack to execute explicitly, which can control iteration and stop; 3. Morris traversal Algorithm: Its essence is to use a large amount of null space of tree species and use the clue tree to realize the clue of the link. The core of the algorithm is: the current node is marked as cur, a. If cur has no left child node, cur right shift cur = cur. right; b. If there is a left child node, find the rightmost node of the left subtree of cur and record it as mostright, b1, if the right of mostright is null, let it point to cur, and shift cur to the left cur = cur.left; b2 If the right of mostright points to cur, let it refer to null, and shift cur to the right cur = cur.right; 4. Use the iterable attribute of js... to simplify the writing


2020.11.03

No.102 Sequence traversal of binary tree

Give you a binary tree, please return the node value obtained by traversing it in order. (That is, visit all nodes layer by layer, from left to right).

 

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

   3
  / \
 9  20
   /  \
  15   7
Return the result of its level traversal:

[
 [3],
 [9,20],
 [15,7]
]

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-tree-level-order-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=102 lang=javascript
 *
 * [102] 二叉树的层序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    const r = [];

    // 构造hash表
    let obj = {};

    // 递归循环 增加一个层级判断n
    const recurse = (curr, n) => {
       if(!curr) return;
       if(!obj[n]) {
        obj[n] = [curr.val]
       } else {
        obj[n].push(curr.val)
       }
       n++;
       recurse(curr.left, n);
       recurse(curr.right, n)
    }

    recurse(root, 0);

    for(let key in obj) {
        r.push(obj[key]);
    }
    
    return r;
};
Option II:
/*
 * @lc app=leetcode.cn id=102 lang=javascript
 *
 * [102] 二叉树的层序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
  if (!root) return [];
  const items = []; // 存放所有节点
  const queue = [root, null]; // null 简化操作
  let levelNodes = []; // 存放每一层的节点

  while (queue.length > 0) {
    const t = queue.shift();

    if (t) {
      levelNodes.push(t.val)
      if (t.left) {
        queue.push(t.left);
      }
      if (t.right) {
        queue.push(t.right);
      }
    } else { // 一层已经遍历完了
      items.push(levelNodes);
      levelNodes = [];
      if (queue.length > 0) {
        queue.push(null)
      }
    }
  }

  return items;
};

There are two ideas for this question: 1. DFS: The key point is to add a level dimension to the judgment, which can be realized by using hash tables or queues, etc.; 2. BFS: Use queues to optimize the number of layers in the loop to achieve breadth first search


2020.11.04

No.103 Zigzag hierarchical traversal of binary tree

Given a binary tree, return the zigzag hierarchical traversal of its node values. (That is, the next layer is traversed from left to right, then from right to left, and so on, alternating between layers).

E.g:
Given a binary tree [3,9,20,null,null,15,7],

   3
  / \
 9  20
   /  \
  15   7
The return to the zigzag hierarchy is traversed as follows:

[
 [3],
 [20,9],
 [15,7]
]

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=103 lang=javascript
 *
 * [103] 二叉树的锯齿形层次遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var zigzagLevelOrder = function(root) {
    const r = [];

    // 构造hash表
    let obj = {};

    const recurse = ( node, n ) => {
        if(!node) return;
        if( !obj[n] ) {
            obj[n] = [node.val];
        } else {
            obj[n].push(node.val)
        };
        n++;
        recurse(node.left, n);
        recurse(node.right, n);
    };

    recurse(root, 0);

    for(let key in obj) {
        // 偶数层从左向右,奇数层从右向左
        if( key % 2 == 0 ) {
            r.push(obj[key]);
        } else {
            r.push(obj[key].reverse());
        }
    }

    return r;
};
Option II:
/*
 * @lc app=leetcode.cn id=103 lang=javascript
 *
 * [103] 二叉树的锯齿形层次遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var zigzagLevelOrder = function (root) {
    let r = []
    let queen = []

    if (root) {
        queen.push([root, 0])
    }

    while (queen.length) {
        let [node, depth] = queen.shift()

        node.left && queen.push([node.left, depth + 1])
        node.right && queen.push([node.right, depth + 1])
        if (!r[depth]) {
            r[depth] = []
        }
        if (depth % 2 === 1) {
            r[depth].unshift(node.val)
        } else {
            r[depth].push(node.val)
        }
    }
    return r
};

Two solutions: 1. DFS: just output the keys in the hash table after the 102 level traversal according to the parity requirements; 2. BFS: construct the queue, and also output the level parity.


2020.11.05

No.105 Construct a binary tree from pre-order and middle-order traversal sequence

The binary tree is constructed according to the pre-order traversal and the middle-order traversal of a tree.

Notice:
You can assume that there are no duplicate elements in the tree.

For example, given

Preorder traversal preorder = [3,9,20,15,7]
Inorder traversal inorder = [9,3,15,20,7]
Return the following binary tree:

   3
  / \
 9  20
   /  \
  15   7

Source: LeetCode
Link: https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=105 lang=javascript
 *
 * [105] 从前序与中序遍历序列构造二叉树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function(preorder, inorder) {
    // 递归终止条件
    if(inorder.length == 0) return null;
    // 根节点一定是前序遍历数组的第一个,在中序遍历数组中获取其位置,可以分离左子树和右子树
    const root = new TreeNode(preorder[0]),
        idx = inorder.indexOf(preorder[0]);
    
    root.left = buildTree(preorder.slice(1,idx+1), inorder.slice(0,idx));
    root.right = buildTree(preorder.slice(idx+1), inorder.slice(idx+1));
    return root;
};
Option II:
/*
 * @lc app=leetcode.cn id=105 lang=javascript
 *
 * [105] 从前序与中序遍历序列构造二叉树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
var buildTree = function(preorder, inorder) {
    pre = i = 0
    build = function(stop) {
        console.log(stop);
        if (inorder[i] != stop) {
            var root = new TreeNode(preorder[pre++])
            root.left = build(root.val)
            i++
            root.right = build(stop)
            return root
        }
        return null
    }
    return build()
};

There are two methods for recursive construction: 1. Use slice to cut the root node and recurse, which consumes more performance, and can be optimized with map and pointers; 2. Save space consumption, here is a stop site for each iteration The output is an extended implementation of the generator function


2020.11.06

No.106 Construct a binary tree from the middle order and the post order traversing the sequence

The binary tree is constructed according to the middle-order traversal and post-order traversal of a tree.

Notice:
You can assume that there are no duplicate elements in the tree.

For example, given

Inorder traversal inorder = [9,3,15,20,7]
Postorder traversal postorder = [9,15,7,20,3]
Return the following binary tree:

   3
  / \
 9  20
   /  \
  15   7

Source: LeetCode
Link: https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=106 lang=javascript
 *
 * [106] 从中序与后序遍历序列构造二叉树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} inorder
 * @param {number[]} postorder
 * @return {TreeNode}
 */
var buildTree = function(inorder, postorder) {
    if( inorder.length == 0 ) return null;
    const root = new TreeNode(postorder[postorder.length - 1]),
        idx = inorder.indexOf(postorder[postorder.length-1]);
    root.left = buildTree(inorder.slice(0,idx), postorder.slice(0, idx));
    root.right = buildTree(inorder.slice(idx+1),postorder.slice(idx,postorder.length-1));
    return root;
};
Option II:
/*
 * @lc app=leetcode.cn id=106 lang=javascript
 *
 * [106] 从中序与后序遍历序列构造二叉树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {number[]} inorder
 * @param {number[]} postorder
 * @return {TreeNode}
 */
var buildTree = function(inorder, postorder) {
    let p = i = postorder.length - 1;
    let build = (stop) => {
        if(inorder[i] != stop) {
            let root = new TreeNode(postorder[p--])
            root.right = build(root.val)
            i--
            root.left = build(stop)
            return root
        }
        return null
    }
    return build()
};

The 105 question is deformed, and the left and right subtrees can be separated by simply taking the roots in the reverse order.


2020.11.09

No.107 Level Traversal of Binary Tree-ii

Given a binary tree, return its node value to traverse from the bottom to the top. (That is, from the layer where the leaf node is located to the layer where the root node is located, traverse from left to right layer by layer)

E.g:
Given a binary tree [3,9,20,null,null,15,7],

   3
  / \
 9  20
   /  \
  15   7
Return its bottom-up level traversal as:

[
 [15,7],
 [9,20],
 [3]
]

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=107 lang=javascript
 *
 * [107] 二叉树的层次遍历 II
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrderBottom = function(root) {
    const r = [];

    // 构造hash表
    let obj = {};

    const recurse = ( node, n ) => {
        if(!node) return;
        if(!obj[n]) {
            obj[n] = [node.val]
        } else {
            obj[n].push(node.val)
        };
        n++;
        recurse(node.left,n);
        recurse(node.right,n)
    };

    recurse(root, 0);

    for( let key in obj) {
        r.push(obj[key])
    };

    return r.reverse();
};
Option II:
/*
 * @lc app=leetcode.cn id=107 lang=javascript
 *
 * [107] 二叉树的层次遍历 II
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrderBottom = function(root) {
  if (!root) return [];
  const items = []; // 存放所有节点
  const queue = [root, null]; // null 简化操作
  let levelNodes = []; // 存放每一层的节点

  while (queue.length > 0) {
    const t = queue.shift();

    if (t) {
      levelNodes.push(t.val)
      if (t.left) {
        queue.push(t.left);
      }
      if (t.right) {
        queue.push(t.right);
      }
    } else { // 一层已经遍历完了
      items.push(levelNodes);
      levelNodes = [];
      if (queue.length > 0) {
        queue.push(null)
      }
    }
  }

  return items.reverse();
};

The idea is the same as that of question 102, just reverse the result.


2020.11.10

No.144 Preorder traversal of binary tree

Give you the root node root of the binary tree, and return the pre-order traversal of its node value.

 

Example 1:
图片

Input: root = [1,null,2,3]
Output: [1,2,3]
Example 2:

Enter: root = []
Output: []
Example 3:

Enter: root = [1]
Output: [1]
Example 4:
图片

Input: root = [1,2]
Output: [1,2]
Example 5:
图片

Input: root = [1,null,2]
Output: [1,2]
 

hint:

The number of nodes in the tree is in the range [0, 100]
-100 <= Node.val <= 100
 

Advanced: The recursive algorithm is very simple, can you do it through an iterative algorithm?

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-tree-preorder-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=144 lang=javascript
 *
 * [144] 二叉树的前序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
    const r = [];

    const recurse = node => {
        if(!node) return;
        r.push(node.val);
        node.left && recurse(node.left);
        node.right && recurse(node.right)
    };

    recurse(root);

    return r;
};
Option II:
/*
 * @lc app=leetcode.cn id=144 lang=javascript
 *
 * [144] 二叉树的前序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
    if(!root) return [];
    const r = [],
          stack = [root];

    while( stack.length > 0 ) {
        const node = stack.pop()
        r.push(node.val);
        // 构造栈,入栈需要先进入右节点,再进入左节点,出栈时才能先左后右
        node.right && stack.push(node.right);
        node.left && stack.push(node.left)
    }

    return r;
};
third solution:
/*
 * @lc app=leetcode.cn id=144 lang=javascript
 *
 * [144] 二叉树的前序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
    const res = [];
    let predecessor = null;

    while (root) {
        if (root.left) {
            // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
            predecessor = root.left;
            while (predecessor.right && predecessor.right !== root) {
                predecessor = predecessor.right;
            }

            // 让 predecessor 的右指针指向 root,继续遍历左子树
            if (!predecessor.right) {
                predecessor.right = root;
                res.push(root.val);
                root = root.left;
            }
            // 说明左子树已经访问完了,我们需要断开链接
            else {
                predecessor.right = null;
                root = root.right;
            }
        }
        // 如果没有左孩子,则直接访问右孩子
        else {
            res.push(root.val);
            root = root.right;
        }
    }

    return res;
};
Option Four:
/*
 * @lc app=leetcode.cn id=144 lang=javascript
 *
 * [144] 二叉树的前序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root) {
    if (root) {
      return [ root.val, ...preorderTraversal(root.left), ...preorderTraversal(root.right) ]
    } else {
      return []
    }
};

The four schemes of in-order traversal with 94: 1. Recursion; 2. Stack optimization; 3. Morris algorithm; 4. js... iteration


2020.11.11

No.145 Post-order traversal of binary tree

Given a binary tree, return its post-order traversal.

Example:

Input: [1,null,2,3]
  1
   \
    2
   /
  3

Output: [3,2,1]
Advanced: The recursive algorithm is very simple, can you do it through an iterative algorithm?

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-tree-postorder-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=145 lang=javascript
 *
 * [145] 二叉树的后序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    const r = [];

    const recurse = node => {
        if(!node) return;

        node.left && recurse(node.left);
        node.right && recurse(node.right);
        r.push(node.val);
    }

    recurse(root);

    return r;
};
Option II:
/*
 * @lc app=leetcode.cn id=145 lang=javascript
 *
 * [145] 二叉树的后序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    if(!root) return [];
    const r = [],
          stack = [root];

    while( stack.length > 0 ) {
        let node = stack.pop();
        node.left && stack.push(node.left);
        node.right && stack.push(node.right);
        r.unshift(node.val);
    }      

    return r;
};
third solution:
/*
 * @lc app=leetcode.cn id=145 lang=javascript
 *
 * [145] 二叉树的后序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    const res = [];
    let predecessor = null;

    while (root) {
        if (root.right) {
            // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
            predecessor = root.right;
            while (predecessor.left && predecessor.left !== root) {
                predecessor = predecessor.left;
            }

            // 让 predecessor 的右指针指向 root,继续遍历左子树
            if (!predecessor.left) {
                predecessor.left = root;
                res.unshift(root.val);
                root = root.right;
            }
            // 说明左子树已经访问完了,我们需要断开链接
            else {
                predecessor.left = null;
                root = root.left;
            }
        }
        // 如果没有左孩子,则直接访问右孩子
        else {
            res.unshift(root.val);
            root = root.left;
        }
    }

    return res;
};
Option Four:
/*
 * @lc app=leetcode.cn id=145 lang=javascript
 *
 * [145] 二叉树的后序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function(root) {
    if (root) {
        return [ ...postorderTraversal(root.left), ...postorderTraversal(root.right), root.val]
    } else {
        return []
    }
};

Same as 144 preorder traversal, there are four solutions: 1. Recursion; 2. Stack; 3. Morris algorithm; 4....Expansion symbol


2020.11.12

No.1008 Preorder traversal to construct a binary search tree

Return the root node of the binary search tree that matches the given preorder traversal preorder.

(Recall that a binary search tree is a type of binary tree, each node of which satisfies the following rules. For any descendant of node.left, the value is always <node.val, and any descendant of node.right, the value is always> node .val. In addition, the preorder traversal first displays the value of node node, then traverses node.left, and then traverses node.right.)

The title guarantees that for a given test case, a binary search tree that meets the requirements can always be found.

 

Example:

Input: [8,5,1,7,10,12]
Output: [8,5,10,1,7,null,12]
图片
 

hint:

1 <= preorder.length <= 100
1 <= preorder[i] <= 10^8
The values in preorder are different from each other

Source: LeetCode
Link: https://leetcode-cn.com/problems/construct-binary-search-tree-from-preorder-traversal
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=1008 lang=javascript
 *
 * [1008] 前序遍历构造二叉搜索树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number[]} preorder
 * @return {TreeNode}
 */
var bstFromPreorder = function(preorder) {
    if(preorder.length == 0) return null;

    const root = preorder.shift();

    let node = new TreeNode(root);

    node.left = bstFromPreorder(preorder.filter(item => item <= root));
    node.right = bstFromPreorder(preorder.filter(item => item > root))
    
    return node;
};
Option II:
/*
 * @lc app=leetcode.cn id=1008 lang=javascript
 *
 * [1008] 前序遍历构造二叉搜索树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number[]} preorder
 * @return {TreeNode}
 */
var bstFromPreorder = function(preorder) {
    if(preorder.length == 0) return null;

    let root = new TreeNode(preorder[0]),
        stack = [root],
        curr,
        child;

    
    for( let i = 1; i < preorder.length; i++ ) {
        child = new TreeNode(preorder[i]);
        curr = stack[0];
        while( stack.length != 0 && stack[0].val < child.val ) {
            curr = stack.shift();
        }
        curr.val > child.val ? curr.left = child : curr.right = child;
        stack.unshift(child);
    }

    return root;
};

Two solutions: 1. Recursion, separating the left and right requirements of the root; 2. Using the recursion in the stack optimization scheme 1.


Summarize:
  1. The common approach to the problem is mainly to use map, hash, stack and other data structures for optimization, and then to use the reduction of the left and right pointers to carry out the number of loops;
  2. The common solution to sub-problems is to use dynamic programming and backtracking pruning to deal with optimization

Binary search tree problem

2020.11.13

No.95 Different Binary Search Tree-ii

Given an integer n, generate all binary search trees composed of 1...n nodes.

 

Example:

Input: 3
Output:
[
 [1,null,3,2],
 [3,2,null,1],
 [3,1,null,null,2],
 [2,1,3],
 [1,null,2,null,3]
]
explain:
The above output corresponds to the following five binary search trees with different structures:

  1         3     3      2      1
   \       /     /      / \      \
    3     2     1      1   3      2
   /     /       \                 \
  2     1         2                 3
 

hint:

0 <= n <= 8

Source: LeetCode
Link: https://leetcode-cn.com/problems/unique-binary-search-trees-ii
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Program:
/*
 * @lc app=leetcode.cn id=95 lang=javascript
 *
 * [95] 不同的二叉搜索树 II
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {number} n
 * @return {TreeNode[]}
 */
var generateTrees = function(n) {
    // 结果个数符合卡特兰数字
    if( n == 0 ) return [];
    
    // 递归构建树
    const buildTree = ( start, end ) => {
        let r = [];
        // 递归终止条件
        if( start > end ) return [null];

        for( let i = start; i <= end; i++ ) {
            // 以i为中心分成左右两边
            let left = buildTree( start, i-1 ),
                right = buildTree( i+1, end );
            
            for( const leftNode of left ) {
                for( const rightNode of right ) {
                    let node = new TreeNode(i);
                    node.left = leftNode;
                    node.right = rightNode;
                    r.push(node)
                }
            }
        }

        return r;
    }

    return buildTree(1, n);
    
};

The main solution is recursive: separate the left and right child nodes according to the root node, then recursively generate the tree, and then splice it to the root node


2020.11.16

No.96 Different Binary Search Trees

Given an integer n, how many kinds of binary search trees with 1 ... n as nodes?

Example:

Input: 3
Output: 5
explain:
Given n = 3, there are 5 binary search trees with different structures:

  1         3     3      2      1
   \       /     /      / \      \
    3     2     1      1   3      2
   /     /       \                 \
  2     1         2                 3

Source: LeetCode
Link: https://leetcode-cn.com/problems/unique-binary-search-trees
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=96 lang=javascript
 *
 * [96] 不同的二叉搜索树
 */

// @lc code=start
/**
 * @param {number} n
 * @return {number}
 */
var numTrees = function(n) {
    // 结果符合卡特兰数 ( 1 / n+1 ) * C(2n,n) => ( 1 / n+1 )*( 2n! / n! * n! )

    const fac = m => {
        let f = 1;
        while( m > 0 ) {
            f*=m;
            m--;
        }
        return f;
    };

    return ( 1 / ( n + 1 ) ) * fac(2*n) / ( fac(n) * fac (n) )
};
Option II:
/*
 * @lc app=leetcode.cn id=96 lang=javascript
 *
 * [96] 不同的二叉搜索树
 */

// @lc code=start
/**
 * @param {number} n
 * @return {number}
 */
var numTrees = function(n) {
    if(n===1||n===0) return 1;
    var res=0;
    for(var i=1;i<=n;i++){
        res += numTrees(i-1) * numTrees(n-i);
    }
    return res;
};
third solution:
/*
 * @lc app=leetcode.cn id=96 lang=javascript
 *
 * [96] 不同的二叉搜索树
 */

// @lc code=start
/**
 * @param {number} n
 * @return {number}
 */
var numTrees = function(n) {
    var dp= new Array(n+1).fill(0);
    dp[0]=1;
    dp[1]=1;
    for(var i=2;i<=n;i++){
        for(var j=1;j<=i;j++){
            dp[i] += dp[j-1]*dp[(i-j)];
        }
    }
    return dp[n];
};

There are three solutions: 1. Mathematical method: the result accords with the Cattelan number, and the general formula of Cattelan number is used to solve it, (1/n+1)*C2nn; 2. Recursion; 3. Dynamic programming


2020.11.17

No.98 Verify Binary Search Tree

Given a binary tree, judge whether it is a valid binary search tree.

Suppose a binary search tree has the following characteristics:

The left subtree of the node only contains numbers less than the current node.
The right subtree of the node only contains numbers greater than the current node.
All left subtrees and right subtrees themselves must also be binary search trees.
Example 1:

enter:
   2
  / \
 1   3
Output: true
Example 2:

enter:
   5
  / \
 1   4
    / \
   3   6
Output: false
Explanation: The input is: [5,1,4,null,null,3,6].
The value of the root node is 5, but the value of its right child node is 4.

Source: LeetCode
Link: https://leetcode-cn.com/problems/validate-binary-search-tree
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=98 lang=javascript
 *
 * [98] 验证二叉搜索树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isValidBST = function(root) {
    // 中序遍历
    const inorderTraversal = root => {
        const r = [];

        const recurse = root => {
            if(!root) return;
            recurse(root.left);
            r.push(root.val);
            recurse(root.right);
        }
            
        recurse(root);

        return r;
    }

    // 判断是否升序
    const isAsec = arr => {
        for(let p1=0,p2=1;p2<arr.length;p1++,p2++) {
            if(arr[p1]>=arr[p2]) return false;
        }
        return true;
    }

    return isAsec(inorderTraversal(root));
};
Option II:
/*
 * @lc app=leetcode.cn id=98 lang=javascript
 *
 * [98] 验证二叉搜索树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isValidBST = function(root) {
      // 递归
      const helper = (root, lower, upper) => {
        if (root === null) {
            return true;
        }
        if (root.val <= lower || root.val >= upper) {
            return false;
        }
        return helper(root.left, lower, root.val) && helper(root.right, root.val, upper);
    }
    return helper(root, -Infinity, Infinity);
};

There are two solutions: 1. Make use of the characteristics of the ascending order of the middle order traversal to construct the middle order traversal to determine whether the order is ascending; 2. Recursion


2020.11.18

No.99 Restore Binary Search Tree

Give you the root node root of the binary search tree. The two nodes in the tree have been swapped by mistake. Please restore this tree without changing its structure.

Advanced: The solution using O(n) space complexity is easy to implement. Can you think of a solution that uses only constant space?

 

Example 1:
图片

Input: root = [1,3,null,null,2]
Output: [3,1,null,null,2]
Explanation: 3 cannot be the left child of 1, because 3> 1. Swap 1 and 3 to make the binary search tree effective.
Example 2:
图片

Input: root = [3,1,4,null,null,2]
Output: [2,1,4,null,null,3]
Explanation: 2 cannot be in the right subtree of 3 because 2 <3. Swap 2 and 3 to make the binary search tree effective.
 

hint:

The number of nodes on the tree is in the range [2, 1000]
-231 <= Node.val <= 231 - 1

Source: LeetCode
Link: https://leetcode-cn.com/problems/recover-binary-search-tree
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=99 lang=javascript
 *
 * [99] 恢复二叉搜索树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {void} Do not return anything, modify root in-place instead.
 */
var recoverTree = function(root) {
    // 1 将错位的二叉搜索树中序遍历,确定错误位点
    // 1.1 中序遍历 
    const inorderTraversal = root => {
        const r = [];

        const recurse = root => {
            if(!root) return;
            recurse(root.left);
            r.push(root.val);
            recurse(root.right);
        }
            
        recurse(root);

        return r;
    }
    // 1.2 获取替换位置
    const replaceIdx = arr => {
        const _arr = arr.slice().sort((a,b)=>a-b);

        let r = [];
        for(let i=0;i<arr.length;i++) {
            if(arr[i] != _arr[i]) {
                r.push( arr[i] )
            }
        };

        return r;
    }

    // 2 替换错误位点
    const swapRoot = ( root, count, x, y ) => {
        if(root) {
            if(root.val == x || root.val == y) {
                root.val = root.val == x ? y : x;
                if(--count == 0) return;
            }
            swapRoot(root.left, count, x, y);
            swapRoot(root.right, count, x, y);
        }
    }

    const [x,y] = replaceIdx(inorderTraversal(root)).slice(0,2);

    swapRoot(root,2,x,y);
};
Option II:
/*
 * @lc app=leetcode.cn id=99 lang=javascript
 *
 * [99] 恢复二叉搜索树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {void} Do not return anything, modify root in-place instead.
 */
var recoverTree = function(root) {
    const swap = (x, y) => {
        const temp = x.val;
        x.val = y.val;
        y.val = temp;
    }
    const stack = [];
    let x = null, y = null, pred = null;

    while (stack.length || root !== null) {
      while (root !== null) {
        stack.push(root);
        root = root.left;
      }
      root = stack.pop();
      if (pred !== null && root.val < pred.val) {
        y = root;
        if (x === null) {
            x = pred;
        }
        else break;
      }
      pred = root;
      root = root.right;
    }
    swap(x, y);
};
third solution:
/*
 * @lc app=leetcode.cn id=99 lang=javascript
 *
 * [99] 恢复二叉搜索树
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {void} Do not return anything, modify root in-place instead.
 */
var recoverTree = function(root) {
      const swap = (x, y) => {
        const temp = x.val;
        x.val = y.val;
        y.val = temp;
    }
      
    let x = null, y = null, pred = null, predecessor = null;

    while (root !== null) {
      if (root.left !== null) {
        // predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
        predecessor = root.left;
        while (predecessor.right !== null && predecessor.right !== root)
          predecessor = predecessor.right;

        // 让 predecessor 的右指针指向 root,继续遍历左子树
        if (predecessor.right === null) {
          predecessor.right = root;
          root = root.left;
        }
        // 说明左子树已经访问完了,我们需要断开链接
        else {
          if (pred !== null && root.val < pred.val) {
            y = root;
            if (x === null) {
                x = pred;
            }
          }
          pred = root;

          predecessor.right = null;
          root = root.right;
        }
      }
      // 如果没有左孩子,则直接访问右孩子
      else {
        if (pred !== null && root.val < pred.val) {
            y = root;
            if (x === null) {
                x = pred;
            }
        }
        pred = root;

        root = root.right;
      }
    }
    swap(x, y);
};

The overall idea is the same as the first solution of the 98 problem, which is to use the middle order traversal to ascending order to obtain the error location. The hard of this problem is mainly to optimize the space complexity. There are three solutions: 1. Use the array to find the error location; 2. Using a pred position, you can stop as long as you get the difference, you don't need to traverse the array completely, which is equivalent to an implicit array; 3. Morris algorithm can reduce the space complexity to a constant level


2020.11.19

No.173 Binary Search Tree Iterator

Implement a binary search tree iterator. You will use the root node of the binary search tree to initialize the iterator.

Calling next() will return the next smallest number in the binary search tree.

 

Example:
图片

BSTIterator iterator = new BSTIterator(root);
iterator.next(); // returns 3
iterator.next(); // returns 7
iterator.hasNext(); // return true
iterator.next(); // returns 9
iterator.hasNext(); // return true
iterator.next(); // returns 15
iterator.hasNext(); // return true
iterator.next(); // returns 20
iterator.hasNext(); // return false
 

hint:

The time complexity of next() and hasNext() operations is O(1) and uses O(h) memory, where h is the height of the tree.
You can assume that the next() call is always valid, that is, when next() is called, there is at least one next smallest number in the BST.

Source: LeetCode
Link: https://leetcode-cn.com/problems/binary-search-tree-iterator
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=173 lang=javascript
 *
 * [173] 二叉搜索树迭代器
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 */
var BSTIterator = function(root) {
    // 中序遍历
    const inorderTraversal = root => {
        const r = [];

        const recurse = root => {
            if(!root) return;
            recurse(root.left);
            r.push(root.val);
            recurse(root.right);
        }
            
        recurse(root);

        return r;
    };
    
    /**
     * 其实返回一个对象就行了,这里用到了js的原型链机制
     * {
        arr: arr, 
        i: 0,
        next: function() {
            let hasNext = this.hasNext(),
                next = hasNext ? this.arr[this.i++] : undefined;
            
            return next;
        },
        hasNext: function() {
            return this.i < this.arr.length;
        }
     * }
     */

    // 挂到this上
    this.arr = inorderTraversal(root);
    this.i = 0;
};

/**
 * @return the next smallest number
 * @return {number}
 */
BSTIterator.prototype.next = function() {
    let hasNext = this.hasNext(),
        next = hasNext ? this.arr[this.i++] : undefined;
    
    return next;
};

/**
 * @return whether we have a next smallest number
 * @return {boolean}
 */
BSTIterator.prototype.hasNext = function() {
    return this.i < this.arr.length;
};

/**
 * Your BSTIterator object will be instantiated and called as such:
 * var obj = new BSTIterator(root)
 * var param_1 = obj.next()
 * var param_2 = obj.hasNext()
 */
Option II:
/*
 * @lc app=leetcode.cn id=173 lang=javascript
 *
 * [173] 二叉搜索树迭代器
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 */
var BSTIterator = function(root) {
    let gen = function* () {
        let stack = [];
        let node = root;
        while (node || stack.length) {
            while (node) {
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            yield node.val;
            node = node.right;
        }
    }
    this.gen = gen();
    this.cursor = this.gen.next();
};

/**
 * @return the next smallest number
 * @return {number}
 */
BSTIterator.prototype.next = function() {
    let value = this.cursor.value;
    this.cursor = this.gen.next();
    return value;
};

/**
 * @return whether we have a next smallest number
 * @return {boolean}
 */
BSTIterator.prototype.hasNext = function() {
    return !this.cursor.done;
};

/**
 * Your BSTIterator object will be instantiated and called as such:
 * var obj = new BSTIterator(root)
 * var param_1 = obj.next()
 * var param_2 = obj.hasNext()
 */

The overall idea is to first obtain the in-order traversal, which can have different optimizations, and then implement the iterator. There are two solutions here: 1. Using the prototype chain mechanism of js; 2. Using the generator that has been implemented in es6 of js


2020.11.20

No.230 The k-th smallest element in the binary search tree

Given a binary search tree, write a function kthSmallest to find the k-th smallest element.

instruction:
You can assume that k is always valid, and 1 ≤ k ≤ the number of elements in the binary search tree.

Example 1:

Input: root = [3,1,4,null,2], k = 1
  3
 / \
1   4
 \
  2
Output: 1
Example 2:

Input: root = [5,3,6,2,4,null,null,1], k = 3
      5
     / \
    3   6
   / \
  2   4
 /
1
Output: 3
Advanced:
If the binary search tree is frequently modified (insertion/delete operations) and you need to find the k-th smallest value frequently, how would you optimize the kthSmallest function?

Source: LeetCode
Link: https://leetcode-cn.com/problems/kth-smallest-element-in-a-bst
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Program:
/*
 * @lc app=leetcode.cn id=230 lang=javascript
 *
 * [230] 二叉搜索树中第K小的元素
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {number}
 */
var kthSmallest = function(root, k) {
    // 中序遍历
    const inorderTraversal = root => {
        const r = [];

        const recurse = root => {
            // 这里对r的长度进行判断剪枝优化
            if(!root || r.length >= k) return;
            recurse(root.left);
            r.push(root.val);
            recurse(root.right);
        }
            
        recurse(root);

        return r;
    };

    return inorderTraversal(root)[k-1]
};

Use in-order traversal to get the k-1th element. See Question 94 for the method of in-order traversal. There are four solutions. Since the tree is frequently modified, it can be optimized according to the length of the array.


2020.11.23

No.235 The nearest common ancestor of a binary search tree

Given a binary search tree, find the nearest common ancestor of two specified nodes in the tree.

The definition of the nearest common ancestor in Baidu Encyclopedia is: "For the two nodes p and q of the rooted tree T, the nearest common ancestor is expressed as a node x, so that x is the ancestor of p and q and the depth of x is as large as possible (A node can also be its own ancestor)."

For example, given the following binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
图片

Example 1:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation: The nearest common ancestor of node 2 and node 8 is 6.
Example 2:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation: The nearest common ancestor of node 2 and node 4 is 2, because by definition the nearest common ancestor node can be the node itself.
 

instruction:

The values of all nodes are unique.
p and q are different nodes and both exist in the given binary search tree.

Source: LeetCode
Link: https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=235 lang=javascript
 *
 * [235] 二叉搜索树的最近公共祖先
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    // 获取路径,返回一个数组链表
    const bstPath = ( root, val ) => {
        const r = [];
        // 递归
        const recurse = node => {
            if(!node) return;
            const v = node.val;
            r.unshift(v);
            if( val > v) {
                recurse(node.right);
            } else if ( val < v ) {
                recurse(node.left);
            } else {
                return;
            }
        };

        recurse(root);

        return r;
    };

    // 根据路径数组,返回两数组最近公共祖先
    const lowestCommonValue = ( arr1, arr2 ) => {
        let s,l;
        if( arr1.length <= arr2.length ) {
            s = arr1;
            l = arr2;
        } else {
            s = arr2;
            l = arr1;
        }

        for(let i=0; i<s.length; i++) {
            if(l.indexOf(s[i]) != -1) {
                return s[i];
            }
        }
    };

    return { val: lowestCommonValue( bstPath(root,p.val), bstPath(root,q.val) )};
};
Option II:
/*
 * @lc app=leetcode.cn id=235 lang=javascript
 *
 * [235] 二叉搜索树的最近公共祖先
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
const lowestCommonAncestor = (root, p, q) => {
  if (p.val < root.val && q.val < root.val) {
    return lowestCommonAncestor(root.left, p, q);
  }
  if (p.val > root.val && q.val > root.val) {
    return lowestCommonAncestor(root.right, p, q);
  }
  return root;
};
third solution:
/*
 * @lc app=leetcode.cn id=235 lang=javascript
 *
 * [235] 二叉搜索树的最近公共祖先
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */

/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
const lowestCommonAncestor = (root, p, q) => {
  while (root) {
    if (p.val < root.val && q.val < root.val) {
      root = root.left;
    } else if (p.val > root.val && q.val > root.val) {
      root = root.right;
    } else {
      break;
    }
  }
  return root;
};

There are three solutions: 1. Construct the path linked list structure to obtain the nearest public node of the array linked list; 2. Recursion; 3. Iteration


2020.11.24

No.501 Mode in Binary Search Tree

Given a binary search tree (BST) with the same value, find all modes (the most frequent element) in the BST.

Assume that BST has the following definition:

The value of the node contained in the left subtree of the node is less than or equal to the value of the current node
The value of the node contained in the right subtree of the node is greater than or equal to the value of the current node
Both left subtree and right subtree are binary search trees
E.g:
Given BST [1,null,2,2],

  1
   \
    2
   /
  2
Return to [2].

Tip: If the mode exceeds 1, no need to consider the output order

Advanced: Can you not use extra space? (Assuming that the overhead of the implicit call stack generated by recursion is not included in the calculation)

Source: LeetCode
Link: https://leetcode-cn.com/problems/find-mode-in-binary-search-tree
The copyright belongs to Lingkou Network. For commercial reprints, please contact the official authorization. For non-commercial reprints, please indicate the source.

Option One:
/*
 * @lc app=leetcode.cn id=501 lang=javascript
 *
 * [501] 二叉搜索树中的众数
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var findMode = function(root) {
    // 构造hash表
    const obj = {};
    const recurse = node => {
        if(!node) return;
        if(obj[node.val]) {
            obj[node.val]++;
        } else {
            obj[node.val] = 1;
        }
        node.left && recurse(node.left);
        node.right && recurse(node.right);
    }
    recurse(root);
    // 获取value的最大值
    let max = Math.max(...Object.values(obj));
    // 对hash表遍历,获取对应最大值的key
    const r = [];
    for(let key in obj) {
        if(obj[key] == max) r.push(key);
    }
    return r;
};
Option II:
/*
 * @lc app=leetcode.cn id=501 lang=javascript
 *
 * [501] 二叉搜索树中的众数
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var findMode = function(root) {
    let base = 0, count = 0, maxCount = 0;
    let answer = [];

    const update = (x) => {
        if (x === base) {
            ++count;
        } else {
            count = 1;
            base = x;
        }
        if (count === maxCount) {
            answer.push(base);
        }
        if (count > maxCount) {
            maxCount = count;
            answer = [base];
        }
    }

    const dfs = (o) => {
        if (!o) {
            return;
        }
        dfs(o.left);
        update(o.val);
        dfs(o.right);
    }

    dfs(root);
    return answer;
};
third solution:
/*
 * @lc app=leetcode.cn id=501 lang=javascript
 *
 * [501] 二叉搜索树中的众数
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var findMode = function(root) {
    let base = 0, count = 0, maxCount = 0;
    let answer = [];

    const update = (x) => {
        if (x === base) {
            ++count;
        } else {
            count = 1;
            base = x;
        }
        if (count === maxCount) {
            answer.push(base);
        }
        if (count > maxCount) {
            maxCount = count;
            answer = [base];
        }
    }

    let cur = root, pre = null;
    while (cur !== null) {
        if (cur.left === null) {
            update(cur.val);
            cur = cur.right;
            continue;
        }
        pre = cur.left;
        while (pre.right !== null && pre.right !== cur) {
            pre = pre.right;
        }
        if (pre.right === null) {
            pre.right = cur;
            cur = cur.left;
        } else {
            pre.right = null;
            update(cur.val);
            cur = cur.right;
        }
    }
    return answer;
};

There are three schemes: 1. The simplest and the best one is to use the hash table structure to judge the mode; 2. Scheme 1 will additionally use the space of the hash table, and use the in-order traversal to use several pointers to judge the output, and the space is complicated. Degree is O(n); 3. Further optimization plan 2, using Morris


维李设论
1.1k 声望4k 粉丝

专注大前端领域发展