「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」
题目
设计并实现一个算法,找出二叉树中某两个节点的第一个共同祖先。不得将其他的节点存储在另外的数据结构中。注意:这不一定是二叉搜索树。
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
3
/ \
5 1
/ \ / \
6 2 0 8
/ \
7 4
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。
来源:力扣(LeetCode)leetcode-cn.com/problems/fi…
解题思路
- 深度优先的方式遍历二叉树查找两个节点;
- 要找的两个节点可能有 3 种存在方式:
- 第一种情况:两个节点在根节点的左右两棵子树中,根节点就是首个公共祖先;
- 第二种情况:如果左子树找到其中一个,右子树中没找到,说明公共祖先在左子树中;
- 第三种情况:如果右子树找到其中一个,左子树中没找到,说明公共祖先在右子树中;
列如从下面的树中找 7 和 4 的首个公共祖先。
3
/ \
5 1
/ \ / \
6 2 0 8
/ \
7 4
从这课树中找到 7 和 4 的首个公共祖先。
- 2 的左、右子树都找到了节点,2 就是首个公共祖先;
- 2 的父节点 5,左边没有找到节点,右边找到了节点,则返回右边的 2;
- 5 的父节点 3,左边找到了节点,右边没有找到节点,则返回左边的 2;
- 3 是最后的根节点,因此 2 就是首个共同祖先;
代码实现
var lowestCommonAncestor = function (root, p, q) {
//如果根节点为空,或根节点等于 p、q,则返回根节点
if (!root || root === p || root === q) return root
//从左子树中找两个节点
const left = lowestCommonAncestor(root.left, p, q)
//从右子树中找两个节点
const right = lowestCommonAncestor(root.right, p, q)
//如果左右两棵子树分别找到了两个节点,当前根节点就是共同祖先
//如果左子树遍历的结果不为空,说明左子树中存在一个节点,则返回左子树结果
//如果右子树遍历的结果不为空,说明右子树中存在一个节点,则返回右子树结果
return left && right ? root : left ? left : right
};
如有错误欢迎指出,欢迎一起讨论!