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

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

难度:简单。
根据二叉搜索树的性质来找答案,如果当前节点大于p,q中的较小值,小于p,q中的较大值,则p,q位于当前节点的左右子树,当前节点为需要寻找的节点。其他情况也根绝二叉搜索树性质进行判断,具体见代码。

正确解法:

/**
 * 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 {
    TreeNode* getNode(TreeNode* root, int min_val, int max_val){
        if(root->val == min_val || root->val == max_val)return root;
        if(root->val > min_val && root->val < max_val)return root;
        if(root->val > max_val){
            return getNode(root->left, min_val, max_val);
        }
        if(root->val < min_val){
            return getNode(root->right, min_val, max_val);
        }
        return NULL;
    }

public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        int min_val = p->val;
        int max_val = q->val;
        if(min_val > max_val)swap(min_val, max_val);
        return getNode(root, min_val, max_val);
    }
};

结果:
在这里插入图片描述

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

难度:简单。

使用一个结构体存储has_p, has_q,分别表示某节点的子树是否包含p和q。

正确解法:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
struct Ans{
    bool has_p, has_q;
    Ans(bool hasP, bool hasQ):has_p(hasP), has_q(hasQ){}
};

class Solution {
    TreeNode* ans = nullptr;

    Ans getNode(TreeNode* root, TreeNode* p, TreeNode* q){
        if(ans != nullptr)return Ans(true, true);
        if(root == nullptr){
            return Ans(false, false);
        }
        Ans left_ans = getNode(root->left, p, q);
        Ans right_ans = getNode(root->right, p, q);
        bool hasP = left_ans.has_p || right_ans.has_p, hasQ = left_ans.has_q || right_ans.has_q;

        if(root->val == p->val)hasP = true;
        else if(root->val == q->val)hasQ = true;
        if(hasP && hasQ && ans == nullptr){
            ans = root;
        }
        return Ans(hasP, hasQ);
    }


public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        getNode(root, p, q);
        return ans;
    }
};

结果:
在这里插入图片描述

可以不使用结构体,只用一个bool来表示每个节点的子树是否包含p或者q,包含其中一个则为true。因为树中的节点是唯一的,因此如果某一节点的左子树和右子树都为true,则肯定是一个包含p,另一个包含q。则该节点一定是p和q的公共祖先。
利用这个思想,可以不适用结构体。

正确解法:

/**
 * 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 {
    TreeNode* ans = nullptr;
    bool getNode(TreeNode* root, TreeNode* p, TreeNode* q){
        if(ans != nullptr)return true;
        if(root == nullptr)return false;
        bool left_ans = getNode(root->left, p, q);
        bool right_ans = getNode(root->right, p, q);
        if(ans == nullptr){
            if((left_ans && right_ans) || 
                ((left_ans || right_ans) && (root->val == p->val || root->val == q->val))){
                ans = root;
            }
        }
        return (left_ans || right_ans || root->val == p->val || root->val == q->val);
    }

public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        getNode(root, p, q);
        return ans;
    }
};

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值