剑指 Offer 68-I/68-II 二叉搜索树的最近公共祖先/二叉树的最近公共祖先C++


2021/2/6二刷
终于结束了二刷之旅,并且三刷了一半的题目。
递归方面比以前好了很多。关于68-II的最后三个连续判断写了新的写法,看起来应该比较易懂一点。


class Solution {
    
    
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    
    
        if(root == NULL) return NULL;
        //如果自己就是所找的结点返回自己
        if(root == p || root == q) return root;
        TreeNode* left = lowestCommonAncestor(root -> left, p, q);
        TreeNode* right = lowestCommonAncestor(root -> right, p,q);
        if(left != NULL && right != NULL) return root;
        if(left == NULL) return right;
        if(right == NULL) return left;
        return NULL;
    }
};

68-I

题目描述

在这里插入图片描述

解法 递归

首先要理解所谓的最近公共祖先,就是两个结点第一次被分开成左右子树的那个结点,那么很明显我们能知道,二叉搜索树的左子树的所有结点小于根结点,右子树的所有节点大于根结点。
所以对于一个结点p
在这里插入图片描述
那么稍加思考就能得出代码

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

在这里插入图片描述
时间复杂度O(N),二叉搜索树退化为链表
空间复杂度O(1)

68-II

题目描述

在这里插入图片描述

解法 后序遍历

身为剑指offer的最后一题,果然没让我失望-----难得一批,众所周知,剑指的简单题比中等题难。
首先我们求解的东西还是没有变化,两个结点第一次被分开成左右子树的那个结点,
然后就直接来看思路吧,要问怎么想到那就是刷题刷过了。
对于每个结点,后序遍历都能保证在左右子树考虑过后再执行自己的函数体。而我们需要知道的,就是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 {
    
    
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    
    
        //后序遍历中遇到p或者q或者已经到头还没遇到p、q
        if(root == NULL || root == p || root == q) return root;
        TreeNode *right = lowestCommonAncestor(root -> right, p, q);
        TreeNode *left = lowestCommonAncestor(root -> left, p, q);
        //右子树和左子树都找不到p或者q
        if(right == NULL && left == NULL) return NULL;
        //左子树找不到右子树找到了,继续往左子树找,返回左子树最终是否找到的结果
        else if(left == NULL) return right;
        //右子树找不到左子树找到了,继续往右子树找,返回右子树最终是否找到的结果
        else if(right == NULL) return left;
        //左右都不为空,说明根结点就是最近公共结点
        return root;
    }
};

在这里插入图片描述
时间复杂度O(N)
空间复杂度O(N)

猜你喜欢

转载自blog.csdn.net/qq_42883222/article/details/112854532
今日推荐