力扣刷题👊【235. 二叉搜索树的最近公共祖先】

353 阅读2分钟

「这是我参与2022首次更文挑战的第 12 天,活动详情查看:2022首次更文挑战

题目链接

235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

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

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

测试用例

示例 1:

image.png

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

条件限制

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

题目分析

题目需要我们在一棵二叉树中查找两个节点的公共祖先节点,并且这个祖先节点尽可能的靠近 p, q 节点(即需要我们找到 p, q 第一次交汇的父节点

一个简单的玩法,我们遍历一次二叉树,记录下所有节点的父节点;然后遍历 q 节点的全部父节点,记录到 set 中,再去遍历 q 的父节点,去 set 中尝试匹配(根据题意,p, q 必定会有一个公共的父节点

需要考虑到的特例情况:

p 可能就是交汇的第一个公共父节点,这个处理简单,我们把 p 也加入到之前定义的 set

q 为交汇的第一个父节点,这种情况下,遍历 q 的父节点一定匹配不到;我们可以为 set 添加 undefined 元素来终止这种情况的遍历查找,然后在返回结果的之后,判断如果匹配结果为 undefined 则返回原始的 q 节点的值

代码实现

 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    let dq = q;
    let obj = {};
    trave(root);
    let parents = new Set([p]);
    while (obj[p.val] != undefined) {
        p = obj[p.val];
        parents.add(p)
    }
    console.log(obj[p.val],p,obj,parents);
    while (!parents.has(q)) {
        q = obj[q.val];
    }
    return q;

    function trave(root) {
        if (root.left != null) {
            obj[root.left.val] = root;
            trave(root.left);
        }
        if (root.right != null) {
            obj[root.right.val] = root;
            trave(root.right);
        }
    }
};

image.png

这次的运行有点出乎意料,仔细排查代码,去掉 console.log,结果就正常多了

image.png

优化

仔细阅读题目,发现需要我们处理的是查找二叉树???换句话,我这种解法算是通用的,如果是在查找二叉树上做匹配,性能应该会提升更多,下次再试试