「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
二叉树的最近公共祖先
题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
解法
首先寻找两个节点的公共祖先,我们第一个需要想到的是要自底向上查找,而二叉树的回溯就是自底向上,在二叉树的三种遍历中,后序遍历是天然的回溯过程,最先处理的一定是叶子节点。而判断一个节点是否是另外两个节点q和p的公共祖先的条件如下:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。
递归三要素:
- 递归函数的参数以及返回值:参数是当前层递归的根节点和要查找的p,q节点,返回值是TreeNode类型,也就是节点
- 递归的单层逻辑:如果该层递归的根节点为空,或者等于p或q,那么返回根节点给上一层,如果不是以上情况,对左,右子树递归查找是否含有p,q节点,如果左右子树分别存在p,q,那么该根节点为最近公共祖先(因为后序遍历是自底向上的),如果左子树存在p,q就返回左子节点,右子树存在p,q就返回右子节点。
var lowestCommonAncestor = function(root, p, q) {
// 使用递归的方法
// 需要从下到上,所以使用后序遍历
// 1. 确定递归的函数
const travelTree = function(root,p,q) {
// 2. 确定递归终止条件
if(root === null || root === p||root === q) {
return root;
}
// 3. 确定递归单层逻辑
let left = travelTree(root.left,p,q);
let right = travelTree(root.right,p,q);
if(left !== null&&right !== null) {
return root;
}
if(left === null) {
return right;
}
return left;
}
return travelTree(root,p,q);
};