This article is participating in the nuggets team online activity, clickCheck spring recruitment positions in big factories
I. Title Description:
The most recent common ancestor of binary trees
Given a binary tree, find the nearest common ancestor of the two specified nodes in the tree.
The definition of the nearest common ancestor in Baidu Encyclopedia is as follows: “For two nodes P and Q with root tree T, the nearest common ancestor is expressed as a node X, which satisfies 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).
Example 1:
Input: root = [3,5,1,6,2,0,8, null, null, 7, 4], p = 5, output q = 1:3: node 5 and 1 recent common ancestor node 3.Copy the code
Example 2:
Input: root = [3,5,1,6,2,0,8, null, null, 7, 4], p = 5, q = 4 output: 5: node 5 nodes and four recent common ancestor is 5. Because by definition the nearest common ancestor node can be the node itself.Copy the code
Example 3:
Input: root = [1,2], P = 1, q = 2 Output: 1Copy the code
Note:
- The number of nodes in the tree is in the range [2, 105].
- -109 <= Node.val <= 109
- All node.val are different.
- p ! = q
- Both p and q exist in a given binary tree.
Ii. Analysis of Ideas:
** Idea 1: ** recursion
Find the nearest common ancestor node of two child nodes. Tree-related problems start with depth-first and breadth-first traversal. Consider breadth-first traversal as long as the problem indicates that it is handled by hierarchy; Other scenarios, especially those that need to be converted to left and right subtrees, can be considered for depth-first traversal. This problem is traversed in depth.
-
Determine the recursive termination condition:
if (! root || root == p || root == q) return rootCopy the code
If root is empty, return root without following the following logic; Root == p or root == q Indicates that the current node root is the parent node.
-
Recurse root.left and root.right to see if these two subtrees have a common parent of P and Q.
let left = lowestCommonAncestor(root.left, p, q) let right = lowestCommonAncestor(root.right, p, q) Copy the code
- If both left and right are null, p and Q are not in the left or right subtree
- If left is null and right is not null, p and Q are in the right subtree
- If right is null and left is not null, p and Q are in the left subtree
- If neither left nor right is null, root is the parent node
Iii. Complete Code:
Idea 1:
var lowestCommonAncestor = function (root, p, q) {
if(! root || root == p || root == q)return root
let left = lowestCommonAncestor(root.left, p, q)
let right = lowestCommonAncestor(root.right, p, q)
if (left == null && right == null) return null
if (left == null) return right
if (right == null) return left
return root
}
Copy the code
A further variation of this problem is to find the common ancestor node. All you need to do is make a small change in the code above. You can think about it.
Complexity analysis:
- Time complexity: O(N), whichNIs the number of nodes in the binary tree. All nodes of the binary tree can be accessed only once, so the time complexity is O(N).
- Space complexity: O(N), where N is the number of nodes in the binary tree. The stack depth of recursive calls depends on the height of the binary tree, which is at worst a chain with a height of N and thus a space complexity of O(N).
Iv. Summary:
The problem of binary trees starts with depth-first or breadth-first traversal. Finding a common ancestor node in a binary tree uses depth-first traversal.