给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
来源:力扣(LeetCode) 链接:力扣
//假定我们已经有了节点函数
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
//构造树形结构的过程省略...
//以下采用递归的做法
var lowestCommonAncestor = function(root, p, q) {
//如果p或q就是根节点, 直接返回根
//考虑到二叉树, 左小右大的特点
//左节点必然小于父节点, 右节点必然大于父节点
//又根据题目说明, 每个节点值是唯一的
//所以做出如下判断
if(p.val == root.val || q.val == root.val) return root;
//如果pq位于根节点两侧, 那么最近公共父节点必然是根节点
if(
(p.val < root.val && q.val > root.val)
||
(p.val > root.val && q.val < root.val)
) return root;
//如果pq均在左侧树, 以左侧下一级节点为根节点, 递归查找
if(p.val < root.val && q.val < root.val) return lowestCommonAncestor(root.left, p, q);
//如果pq均在右侧树, 以右侧下一级节点为根节点, 递归查找
if(p.val > root.val && q.val > root.val) return lowestCommonAncestor(root.right, p, q);
};
递归通常的问题是对空间的损耗, 可以改为循环迭代方式
var lowestCommonAncestor = function(root, p, q) {
while(root) {
//如果p或q就是根节点, 直接返回根
if(p.val == root.val || q.val == root.val) return root;
//如果pq位于根节点两侧, 那么依然返回根
if(
(p.val < root.val && q.val > root.val)
||
(p.val > root.val && q.val < root.val)
) return root;
//如果pq均在左侧树, 以左侧下一级节点为根节点
if(p.val < root.val && q.val < root.val)
root = root.left; //替换root, 进入下一次循环
//如果pq均在右侧树, 以右侧下一级节点为根节点, 递归查找
if(p.val > root.val && q.val > root.val)
root = root.right; //替换root, 进入下一次循环
}
};