Problem Description
Given a binary 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 two nodes p and q of the rooted tree T, the nearest common ancestor is expressed as a node x, satisfying that x is the ancestor of p and q and the depth of x is as large as possible (a A node can also be its own ancestor)."
Example 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
Example 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
Example 3:
输入:root = [1,2], p = 1, q = 2
输出:1
prompt:
树中节点数目在范围 [2, 105] 内。
-109 <= Node.val <= 109
所有 Node.val 互不相同 。
p != q
p 和 q 均存在于给定的二叉树中。
Problem-solving ideas:
The idea of the problem solution is referenced from https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/236-er-cha-shu-de-zui-jin-gong-gong -zu-xian-hou-xu/ The definition of
nearest common ancestor : Let node root be a common ancestor of node p, q, if its left child node root.left and right child node root.right are not common to p, q Ancestor, then said root is "the nearest common ancestor" .
According to the above definition, if root is the nearest common ancestor of p, q, it can only be one of the following:
p and q are in the root's subtree, and separate the opposite sides of root (that is, in the left and right subtrees respectively) ;
p = root, and q is in the root's left or right subtree;
q = root, and p is in the left or right subtree of root;
Consider post-order traversal of the binary tree through recursion, and return when it encounters node p or q. Backtracking from bottom to top, when the nodes p, q are on the opposite side of the node root, the node root is the nearest common ancestor, and it returns to the root upwards.
Recursive analysis:
termination conditions:
- When the leaf node is crossed, null is directly returned;
- When root is equal to p, q, then directly return to root;
Recursive work:
- Turn on the recursive left child node, and the return value is recorded as left;
- Turn on the recursive right child node, and the return value is recorded as right;
Return value: According to left and right, it can be expanded into four situations;
- When left and right are empty at the same time: it means that the left/right subtrees of root do not contain p, q, and null is returned;
- When left and right are not empty at the same time: indicating that p and q are listed on the opposite side of root (respectively in the left/right subtree), so root is the nearest common ancestor, return to root;
- When left is empty, right is not empty: both p and q are not in the left subtree of root, and return right directly. Specifically, it can be divided into two situations: one of
p and q is in the right subtree of root, at this time right points to p (assumed to be p);
both nodes of p and q are in the right subtree of root, at this time right Point to the nearest common ancestor node; - When left is not empty, rightr is empty: the same as in case 3.
Observation found that situation 1. can be combined into 3. and 4.
Implementation code
class Solution {
public TreeNode SearchAncester(TreeNode root,TreeNode p, TreeNode q){
//如果root为空,那么直接返回空
if(root==null){
return null;
}
//如果root为p结点或者q结点,那么就返回root
if(root==p || root==q){
return root;
}else{
//在左子树和右子树中寻找p,q
TreeNode leftNode=SearchAncester(root.left,p,q);
TreeNode rightNode=SearchAncester(root.right,p,q);
//左子树为空,说明在右子树中,如果最终右子树也为空,那么直接返回空
if(leftNode==null){
return rightNode;
//右子树为空,说明在左子树中
}else if(rightNode==null){
return leftNode;
}else{
//如果左右子树都不为空,那么最近公共祖先结点就是root
return root;
}
}
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null){
return root;
}
return SearchAncester(root,p,q);
}
}