“This is the second day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”
The role of binary trees
Understand the basics of high-level data structures
Graph of TD binary tree - > complete binary tree Binary tree - > how tree/binary tree forest - > binary sort tree Complete binary tree > pile of full binary tree -- - > priority queue how tree/forest tree -- > dictionary More tree/forest -- > AC automata tree/forest --> set binary sort tree --> AVL tree binary sort tree --> 2-3 tree binary sort tree --> red black tree multi-fork sort tree --> B -- tree /B+ tree
Heap and priority queue are the best tools to maintain the maximum value of collection
Dictionary tree and AC automata are the most powerful tools for string and its related conversion problems
And collection is the magic weapon for connectivity problems
AVL tree, 2-3 tree and red-black tree are the basic implementation of important data retrieval containers in the language standard library
B- tree and B+ tree are important data structures at the bottom of file system and database
The best way to practice your recursive skills
Design/understand recursive programs
- Mathematical induction -> structural induction
- Give recursive functions an explicit meaning
- Thinking about boundary conditions
- Implement the recursive process
- K0 is correct
- Let’s say ki -> ki+1
- k0 -> k1 -> … kn-1 -> kn
function fib(n) { //fib(n) represents the value of the NTH Fibonacci sequence
if (n <= 2) return n; / / k0 is correct
return fib(n-1) + f(n-2); // Assume that ki is correct
}
Copy the code
Left child right brother notation saves space
Binary tree algorithm (recursive)
Antecedent traversal of binary tree -144
Give you the root node of the binary tree, root, and return a pre-traversal of its node value.
Example 1:
Input: root = [1, NULL,2,3] Output: [1, 3] Example 2:
Input: root = [] Output: []
Example 3:
Input: root = [1] Output: [1]
Example 4:
Input: root = [1,2] output: [2]
Example 5:
Input: root = [1, NULL,2]
const preorder = function(root, arr) {
if(! root)return;
arr.push(root.val)
preorder(root.left, arr)
preorder(root.right, arr)
}
const preorderTraversal = function(root) {
const arr = []
preorder(root, arr);
return arr;
};
Copy the code
N Preorder traversal of the fork tree -589
/ * * *@param {Node|null} root
* @return {number[]}* /
const preorder = function(root) {
let arr = [];
preorderFunc(root, arr)
return arr
};
const preorderFunc = function(root, arr) {
if(! root)return;
arr.push(root.val);
if (root.children) {
root.children.forEach(item= > {
preorderFunc(item, arr)
})
}
}
Copy the code
Flip the binary tree -226
- Function Meaning: Invert the binary tree with root node
- Boundary condition: no need to flip when root is empty
- Recursion: Flip the left subtree of root and flip the right subtree of root
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; *} * /
/ * * *@param {TreeNode} root
* @return {TreeNode}* /
var invertTree = function(root) {
if(! root)return null;
let tempNode = invertTree(root.left);
root.left = invertTree(root.right);
root.right = tempNode;
return root;
};
Copy the code
Finger Offer 32-ii. Print binary tree II from top to bottom
- Function meaning: Put the value of each node into the appropriate layer (need to record the number of layers)
- Boundary condition: No value is required when root is null
- Recursive process: first put the current node value, then put the left and right nodes in the next level of the array
Recursive solution:
const levelOrder = function(root) {
let arr = []
_levelOrder(root, arr, 0)
return arr
};
const _levelOrder = function(root, arr, i) {
if(! root)return;
arr[i] ? arr[i].push(root.val) : arr[i] = [root.val];
_levelOrder(root.left, arr, i+1)
_levelOrder(root.right, arr, i+1)}Copy the code
Queue solution:
const levelOrder = function (root) {
if(! root)return []
const queue = [root];
const arr = [];
while (queue.length > 0) {
const temp = [];
let i = queue.length
for(; i >0; i--) {
const node = queue.shift();
temp.push(node.val)
if (node.left) {
queue.push(node.left)
}
if (node.right) {
queue.push(node.right)
}
}
arr.push(temp)
}
return arr
};
Copy the code
107. Sequence traversal of binary trees II
Similar to finger Offer 32-ii. Print binary tree II from top to bottom, just flip the array.
const levelOrderBottom = function(root) {
const result = [];
_levelOrderBottom(root, result, 0);
/ / tips
for(let i=0, j = result.length - 1; i < j; i++, j--) {
const temp = result[j];
result[j] = result[i];
result[i] = temp;
}
return result;
//return result.reverse()
};
const _levelOrderBottom = function(root, arr, idx) {
if(! root)return;
arr[idx] ? arr[idx].push(root.val) : arr[idx] = [root.val];
root.left && _levelOrderBottom(root.left, arr, idx + 1);
root.right && _levelOrderBottom(root.right, arr, idx + 1);
}
Copy the code
103. Serrated sequence traversal for binary trees
Again, as long as the odd number of layers are flipped
/** * 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[][]}* /
const zigzagLevelOrder = function (root) {
const result = [];
_zigzagLevelOrder(root, result, 0);
for (let i = 1; i < result.length; i += 2) {
result[i] = result[i].reverse()
}
return result
};
const _zigzagLevelOrder = function (root, arr, idx) {
if(! root)return;
arr[idx] ? arr[idx].push(root.val) : arr[idx] = [root.val];
root.left && _zigzagLevelOrder(root.left, arr, idx + 1);
root.right && _zigzagLevelOrder(root.right, arr, idx + 1);
}
Copy the code
110. Balanced binary trees
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; *} * /
/ * * *@param {TreeNode} root
* @return {boolean}* /
const isBalanced = function(root) {
return getHeight(root) >= 0
};
const getHeight = (root) = > {
if(! root)return 0;
const left = getHeight(root.left);
const right = getHeight(root.right);
// If the left and right absolute values are greater than 1, it is not balanced
if (Math.abs(left - right) > 1) return -2;
// If the left or right subtrees are less than 0, there is an imbalance
if (left < 0 || right < 0) return -2;
// Return the higher value of the left and right subtrees +1= the current node height
return Math.max(left, right) + 1;
}
Copy the code
112. Sum of paths
/** * 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} targetSum
* @return {boolean}* /
const hasPathSum = function(root, targetSum) {
if(! root)return false;
// If it is a leaf node, determine whether the current value is the target value
if(! root.left && ! root.right)return root.val === targetSum;
return hasPathSum(root.left, targetSum - root.val)
|| hasPathSum(root.right, targetSum - root.val);
};
Copy the code
105. Construct a binary tree by traversing pre-order and middle-order sequences
/** * 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
* @param {number[]} inorder
* @return {TreeNode}* /
const buildTree = function (preorder, inorder) {
if(! preorder.length)return null;
const result = new TreeNode();
const root = preorder.shift();
result.val = root;
let inIdx = 0;
while(inorder[inIdx] ! == root) inIdx++;const leftPre = preorder.slice(0, inIdx);
const rightPre = preorder.slice(inIdx);
const leftIn = inorder.slice(0, inIdx);
const rightIn = inorder.slice(inIdx + 1);
result.left = buildTree(leftPre, leftIn);
result.right = buildTree(rightPre, rightIn);
return result;
};
Copy the code
222. Number of nodes in a complete binary tree
/** * 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 countNodes = function(root) {
if(! root)return 0;
return 1 + countNodes(root.left) + countNodes(root.right)
};
Copy the code
The KTH largest node in the binary search tree
Given a binary search tree, find the KTH largest node.
Note: binary search tree, the left node must be smaller than the right node. That is, the middle order traversal of a binary search tree must be an ordered array.
First calculate the number of the right node and determine the position of the KTH node. Go to the
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; *} * /
/ * * *@param {TreeNode} root
* @param {number} k
* @return {number}* /
const kthLargest = function(root, k) {
const r_count = countTree(root.right);
if (k <= r_count) return kthLargest(root.right, k);
if (k === r_count + 1) return root.val;
return kthLargest(root.left, k - r_count - 1);
};
const countTree = (root) = > {
if(! root)return 0;
return countTree(root.left) + countTree(root.right) + 1;
}
Copy the code
Offer 26. Substructure of tree
Input two binary trees A and B to determine whether B is A substructure of A. (Convention that an empty tree is not a substructure of any tree)
B is A substructure of A, that is, A has the same structure and node value as B.
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = this.right = null; *} * /
/ * * *@param {TreeNode} A
* @param {TreeNode} B
* @return {boolean}* /
// check whether it is a subtree
const isSubStructure = function(A, B) {
if(! B || ! A)return false;
if (B.val === A.val && is_Match(A,B)) return true;
return isSubStructure(A.left, B) || isSubStructure(A.right, B)
};
// Check whether the nodes match
const is_Match = (A, B) = > {
if(! B)return true;
if(! A)return false;
if(B.val ! == A.val)return false;
return is_Match(A.left, B.left) && is_Match(A.right, B.right);
}
Copy the code