Leetcode 236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大 (一个节点也可以是它自己的祖先)

Leetcode 236. 二叉树的最近公共祖先_第1张图片

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。

【问题介绍】:
这种题属于最近公共祖先问题中的一次性查询问题。
如果是一次查询,那么解法还是比较多的,例如两次搜索、递归、后续遍历等。如果是多次查询就很难了,需要用到倍增法的预处理。
一次查询和多次查询在力扣上都有题目,下面结合例题给出具体解法。注意多次查询的题目很难,大家可以结合自身对知识的掌握情况选做。

给定一棵有根树,若 z 既是 x 的祖先,又是 y 的祖先,
则称 z 是 x,y 的最近公共祖先,记为 z = lca(x, y)lca(x, y) 的两条重要性质:

lca(x, y) 是 x 到根的路径和 y 到根的路径的交点。
lca(x, y) 是 x 到 y 的路径中顺度最小的节点。。

【思路】:
直接暴力法。
遍历每个节点,判断该节点是否同时有a,b两个子节点。如果是,就把它加到栈中,然后继续遍历。最后取出栈中最上面的一个节点,即为最近的公共祖先。

【代码】:

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p      p,q都是两个子节点
 * @param {TreeNode} q
 * @return {TreeNode}
 */

//判断某个节点是不是含有val这个子节点
//return boolean
var hasThisChild = function(node, val){
    if(node != null){
        if(node.val == val) return true;
        return hasThisChild(node.left, val) || hasThisChild(node.right, val);
    }else{
        return false;
    }
}

//return void
var preOrder = function(node, firstChild, secondChild, stack){
    if(node != null){
        //针对每个节点,去判断它是否含有某个val的子节点
        let tag = hasThisChild(node, firstChild.val) && hasThisChild(node, secondChild.val);
        if(tag){
            stack.push(node);
        }
        preOrder(node.left, firstChild, secondChild, stack);
        preOrder(node.right, firstChild, secondChild, stack);
    }
}

var lowestCommonAncestor = function(root, p, q) {
    var stack = [];
    preOrder(root, p, q, stack);
    var len = stack.length;
    return stack[len - 1];
};

你可能感兴趣的:(树,LeetCode,leetcode,算法)