剑指 Offer 68 二叉树的最近公共祖先

这篇博客介绍了如何使用二叉搜索树的特性来高效地找到两个节点的最近公共祖先。作者首先给出了两种解决方案:递归和二分查找,然后通过将普通二叉树转换为二叉搜索树,简化了问题。最后,博主分享了一位大佬的简洁思路,通过判断节点在根节点的左右子树位置来直接找到最近公共祖先。
摘要由CSDN通过智能技术生成

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

题目描述

在这里插入图片描述
在这里插入图片描述

菜鸡思路:

  1. 二叉树,就是递归
  2. 二叉搜索树,还可以二分查找避免递归

菜鸡代码:

递归

/**
 * 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) {
            root = lowestCommonAncestor(root->left, p, q);
        }
        if (p->val > root->val && q->val > root->val) {
            root = lowestCommonAncestor(root->right, p, q);
        }
        return root;
    }
};

二分查找

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        int min = p->val < q->val ? p->val : q->val;
        int max = p->val + q->val - min;
        TreeNode *result = root;
        while (root) {
            if (root->val >= min && root->val <= max) {
                return root;
            } else if (root->val > max) {
                root  = root->left;
            } else if (root->val < min) {
                root = root->right;
            }
        }
        return result;
    }
};

剑指 Offer 68 - II. 二叉树的最近公共祖先

题目描述

在这里插入图片描述
在这里插入图片描述

菜鸡思路:

转化为二叉搜索树,利用上一道题的代码

菜鸡代码:

/**
 * 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:
    unordered_map<TreeNode*, int>myMap;
    int count = 0;
    void search(TreeNode* root) {
        if (!root) {
            return;
        }
        search(root->left);
        myMap.insert({root, count++});
        search(root->right);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        search(root);
        int min = myMap[p] < myMap[q] ? myMap[p] : myMap[q];
        int max = myMap[p] + myMap[q] - min;
        TreeNode *result = root;
        while (root) {
            if (myMap[root] >= min && myMap[root] <= max) {
                return root;
            } else if (myMap[root] > max) {
                root  = root->left;
            } else if (myMap[root] < min) {
                root = root->right;
            }
        }
        return result;
    }
};

大佬思路:

对于一颗树来说,如果节点p、q分别分布在root的左右子树中,那么节点p、q的最近公共祖先为root;如果p、q均只分布在root的一侧(左子树或者是右子树)中,我们则可以递归的处理相同的问题,即在一颗子树(root->left或者root->right)中判断节点p、q的最近公共祖先。

大佬代码:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) {
            return NULL;
        }
        if(root == p || root == q) {
            return root;
        }
        auto left = lowestCommonAncestor(root->left, p, q);
        auto right = lowestCommonAncestor(root->right, p, q);
        if (left && right) {
            return root;
        }
        if (left) {
            return left;
        }
        return right;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值