题目描述
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 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
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉搜索树中。
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/er… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
总体思路: 所谓公共祖先,也就是从根节点分别到两个子节点路径上的交叉点。
例如例子2
- 根节点到6到2节点的路径为[6,2],根节点到4节点的路径为[6,2,4]
- 其中重合的有6,2节点,这两个节点都是2和4的公共祖先,其中最近的是2节点。
接下来的问题就是如何得到路径
- 我们创建一个辅助函数help,pLine为p的路径列表,qLine为q的路径列表
- 然后开始递找到目标节点
- 当前节点值小于目标值则目标在当前右子树中,就继续遍历右子节点help(tree.right,key,list);
- 当前节点值大于目标值则目标在当前左子树中,就继续遍历左子节点help(tree.left,key,list);
- 直到找到节点,结束递归得到路径
代码
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
var lowestCommonAncestor = function(root, p, q) {
//辅助函数,递归获取路径
var help=function(tree,key,list){
if(!tree) return;
list.push(tree);//节点加入路径
if(key.val>tree.val){//目标节点在当前节点的右边
help(tree.right,key,list);
}else if(key.val<tree.val){//目标节点在当前节点的左边
help(tree.left,key,list);
}else{
return;//找到当前节点
}
}
let pLine=[];//p路径
let qLine=[];//q路径
help(root,p,pLine);//获取路径
help(root,q,qLine);
let result="";//结果
//从头部遍历,最后一个重合的点就是最近公共祖先
for(let i=0;i<Math.min(pLine.length,qLine.length);i++){
if(pLine[i].val===qLine[i].val)result=pLine[i];
}
return result;
};