LeetCode 235. Lowest Common Ancestor of a Binary Search Tree

题目

Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Given binary search tree:  root = [6,2,8,0,4,7,9,null,null,3,5]

 

Example 1:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation: The LCA of nodes 2 and 8 is 6.

Example 2:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

 

Note:

  • All of the nodes' values will be unique.
  • p and q are different and both values will exist in the BST.

这道题乍一看觉得好难,一点思路都没有,但是看了解答以后真的豁然开朗。需要利用二叉搜索树的性质,一个节点的左子节点永远比这个节点小,而右子节点永远比这个节点大。如果需要找到两个节点的最低公共祖先,那么就是从上往下遍历的过程中最后一个满足p和q两个节点分别在它的左右的情况,也就是p和q分别比当前节点的值要小或者大。如果p、q同时在一个节点的同一侧的话,就沿着这一侧的子节点继续往下找。但是注意到,还有一种情况是p和q之中有一个节点是另一个节点的祖先节点,如下图中的第二种和第三种:

在这种情况下,我们依旧可以通过前面的判断条件来判断是否找到了这个节点。因为如果p和q任意一个节点就是当前的根节点的话,我们就直接返回当前的根节点就行,也就是下面代码中的else。代码时间复杂度在最坏的情况下(如果这棵树非常不平衡并且p和q都处在很深的地方),这时候几乎要遍历所有的节点,就是O(n),而如果是平衡二叉树则只需要O(logn),运行时间36ms,79.9%,空间由于用到了递归栈就是复杂度O(n)(万一树不平衡那它的深度就是n了),25.6M,100%。(为了看这个百分比我又提交了一次,发现这次运行了40ms,只有50.7%,空间25.7M,100%)代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if ((p->val < root->val) && (q->val < root->val)) {
            return lowestCommonAncestor(root->left, p, q);
        }
        else if ((p->val > root->val) && (q->val > root->val)) {
            return lowestCommonAncestor(root->right, p, q);
        }
        else {
            return root;
        }
    }
};

2020.10.06 Java:

Runtime: 4 ms, faster than 66.18% of Java online submissions for Lowest Common Ancestor of a Binary Search Tree.

Memory Usage: 39.7 MB, less than 96.73% of Java online submissions for Lowest Common Ancestor of a Binary Search Tree.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (p.val < root.val && q.val < root.val) {
            return lowestCommonAncestor(root.left, p, q);
        }
        if (p.val > root.val && q.val > root.val) {
            return lowestCommonAncestor(root.right, p, q);
        }
        return root;
    }
}

另外一种是迭代的写法,思路和递归一毛一样,并且写起来也很方便,不需要用到什么栈啊队列啊之类的(好像是因为不用backtrace?),时间40ms,50.74%,空间25.5M,100%:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        while (root) {
            if ((p->val < root->val) && (q->val < root->val)) {
                root = root->left;
            }
            else if ((p->val > root->val) && (q->val > root->val)) {
                root = root->right;
            }
            else {
                return root;
            }
        }
        return root;
    }
};

2020.10.12 Java:

Runtime: 3 ms, faster than 100.00% of Java online submissions for Lowest Common Ancestor of a Binary Search Tree.

Memory Usage: 39.8 MB, less than 7.98% of Java online submissions for Lowest Common Ancestor of a Binary Search Tree.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while (root != null) {
            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;
            }
        }
        return root;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值