236. 二叉树的最近公共祖先
难度:中等
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。
思路
如果这个题看不明白的话可以先看看求二叉搜索树的最近公共祖先
共有三种情况
- 两个节点都比当前节点小,则都在当前节点的左子树上
- 两个节点都比当前节点大,则都在当前节点的右子树上
- 一个比当前节点大(等于),一个比当前节点小(等于),则当前节点就是两个节点的最近公共祖先
但是实现的话我们无法根据当前节点的值去判断是在当前节点的左边还是在当前节点的右边
所以我们只能遍历当前节点的所有子树,看能不能找到至少一个节点在其左边或者右边
- 如果当前节点和其中一个节点相等,则直接返回
- 如果其左侧和右侧各有一个节点,则说明当前节点就是最近公共子节点
- 如果二者都在一边,则最近最先必然在那一侧中的某个节点处
package cn.edu.xjtu.carlWay.tree.commonAncestor;
import cn.edu.xjtu.Util.TreeNode.TreeNode;
/**
* 236. 二叉树的最近公共祖先
* 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
* <p>
* 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
* <p>
* https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/
*/
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
}
// 该节点及其子树中必然包含至少一个节点
if (root.val == p.val || root.val == q.val) {
return root;
}
// 判断当前节点的左子树与右子树是否包含至少一个节点
TreeNode leftNode = lowestCommonAncestor(root.left, p, q);
TreeNode rightNode = lowestCommonAncestor(root.right, p, q);
if (leftNode != null && rightNode != null) {
// 如果左子树与右子树都包含一个节点,则说明当前节点就是最近公共子节点
return root;
} else {
// 否则二者必然在不为null的那一边
return leftNode == null ? rightNode : leftNode;
}
}
}