• 二叉树LCA--leetcode236题


    二叉树的最近公共祖先

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
    例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

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

    1.哈希表解法
    (1)创建队列queue进行二叉树层序遍历
    (2)设置map映射父子结点关系,从而可以从子结点访问到父节点
    (3)利用map记录的联系找出p所有的祖宗结点存在set
    (4)遍历q的父节点,如果存在于set中,则为最近公共祖先,直接返回

    var lowestCommonAncestor = function (root, p, q) {
        /* 如果root为p或q直接返回 */
        if (!root || root === p || root === q) return root;
        let queue = [root];
        let map = new WeakMap();
        /* 遍历二叉树,存映射关系 */
        while (queue.length) {
            let size = queue.length;
            while (size--) {
                let front = queue.shift();/* 队首 */
                if (front.left) {
                    queue.push(front.left);
                    map.set(front.left, front);
                }
                if (front.right) {
                    queue.push(front.right);
                    map.set(front.right, front);
                }
            }
        }
        /* 记录p的所有祖先 */
        let acts = new Set();
        while (p) {
            acts.add(p);//放到set中
            p = map.get(p);//父结点
        }
        /* 查找公共祖先 */
        while (q) {
            if (acts.has(q)) return q;
            q = map.get(q);
        }
    };
    

    2.深度优先搜索解法
    原理:根据p,q是否分别在两侧子树判断LCA
    (1)深度优先遍历二叉树,如果当前节点为 p 或者 q,直接返回这个节点,
    (2)不符合以上条件,查看左右孩子,左孩子中不包含 pq 则去找右孩子,右孩子不包含 p 或者 q 就去找左孩子
    (3)左右孩子中都存在 p 或者 q, 那么这个节点就是LCA(只有对于最近公共祖先p,q才会在不同侧)

    var lowestCommonAncestor = function (root, p, q) {
        /* root为null,p,q这三种情况时返回 */
        if (!root || root === p || root === q) return root;
        /* 查找左子树 */
        let left = lowestCommonAncestor(root.left, p, q);
        /* 查找右子树 */
        let right = lowestCommonAncestor(root.right, p, q);
        /* 左子树不存在p/q */
        if (!left) return right;
        else if (!right) return left;
        else return root;//左右子树各存在p,q中的一个,为公共祖先
    };
    

    补充

    对于二叉搜索树,还可以进行优化,通过权值大小比对可以确定p,q相对root的位置,如果p,q分别在root的两侧,则root就是最近公共祖先。
    题目链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/submissions/
    递归法:

    var lowestCommonAncestor = function (root, p, q) {
        if (!root || root === p || root === q) return root;
        /* 判断p,q在root的哪边,如果一左一右则root就是最近公共祖先 */
        if (root.val > p.val && root.val > q.val) {
            return lowestCommonAncestor(root.left, p, q);
        }
        else if (root.val < p.val && root.val < q.val) {
            return lowestCommonAncestor(root.right, p, q);
        }
        else {
            return root;
        }
    };
    

    非递归:

    var lowestCommonAncestor = function (root, p, q) {
        if (!root || root === p || root === q) return root;
        while (root) {
            if (root.val > p.val && root.val > q.val) {
                root = root.left;
            } else if (root.val < p.val && root.val < q.val) {
                root = root.right;
            } else {
                return root;
            }
        }
    };
    
  • 相关阅读:
    [C++再学习系列] 深入new/delete:Operator new的全局重载
    [C++再学习系列] 函数模板和类模板
    [C++再学习系列] 模板函数的自定义点
    [C++再学习系列] STL容器删除操作总结
    How to create a sizelimited filesystem
    CodeSmith 破解和注册
    LINQ to SQL学习的几个问题
    SQLSERVER2005 分区表
    google工具栏和搜狗拼音叠加问题
    C#中构成函数重载有哪些条件和特征?
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/12726192.html
Copyright © 2020-2023  润新知