【面试-leetcode235】查找二叉搜索树公共祖先(递归+迭代)

712 阅读3分钟

freysteinn-g-jonsson-s94zCnADcUs-unsplash.jpg 这是 leetcode 面试刷题一题多解系列的第10篇,练习分别使用递归和迭代的方式查找二叉树的最近公共祖先。

题目

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

来源:力扣(LeetCode)
链接:leetcode.cn/problems/lo…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析

二叉搜索树的性质是,左子树的所有节点的值都小于根节点的值,右子树的所有节点的值都大于根节点的值。因此,在二叉搜索树中查找某个节点时,我们可以根据节点的值与当前根节点的值的大小关系,来判断要查找的节点在左子树中还是右子树中。

根据二叉搜索树的性质,可以使用递归的方式查找最近公共祖先。首先,比较 p 和 q 的值与当前根节点的值的大小关系,如果都小于当前根节点的值,那么最近公共祖先一定在当前节点的左子树中;如果都大于当前根节点的值,那么最近公共祖先一定在当前节点的右子树中;如果一个大于当前根节点的值,一个小于当前根节点的值,那么当前节点就是它们的最近公共祖先。如果当前节点为空,说明没有找到 p 或 q 中的一个,返回 null。

题解1---递归

递归的过程可以通过函数实现。函数的参数是当前节点 root、要查找的节点 p 和 q。函数的返回值是最近公共祖先节点。递归的结束条件是当前节点为空或者找到了 p 或 q 中的一个。

/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    if (root === null) {
        return null;
    }
    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;
    }

};

题解2---迭代

除了递归,我们还可以使用迭代的方式查找最近公共祖先。与递归不同的是,迭代过程中需要维护一个栈来记录访问过的节点,以及它们的父节点。

迭代的过程中,我们可以使用一个 while 循环,不断地将当前节点 root 和要查找的节点 p、q 进行比较,然后根据比较结果选择向左或向右遍历。遍历的过程中,将访问的节点和它们的父节点分别入栈。当遍历到 p 或 q 中的一个节点时,就停止遍历,并返回它的祖先节点。

var lowestCommonAncestor = function(root, p, q) {
    let stack = [root];
    let parent = new Map();
    parent.set(root, null);
    while (!parent.has(p) || !parent.has(q)) {
        let node = stack.pop();
        if (node.left !== null) {
            parent.set(node.left, node);
            stack.push(node.left);
        }
        if (node.right !== null) {
            parent.set(node.right, node);
            stack.push(node.right);
        }
    }
    let ancestors = new Set();
    while (p !== null) {
        ancestors.add(p);
        p = parent.get(p);
    }
    while (!ancestors.has(q)) {
        q = parent.get(q);
    }
    return q;
};

这两种方法都可以在时间复杂度和空间复杂度上达到 O(h),其中 h 是二叉搜索树的高度。递归的代码简洁明了,易于理解和实现,而迭代的方法更加直观,可以更好地掌握栈的使用技巧。

我的更多前端资讯

欢迎大家技术交流 资料分享 摸鱼 求助皆可 —链接