力扣(LeetCode)236. 二叉树的最近公共祖先(C语言)

一、环境说明

  1. 本文是 LeetCode 236. 二叉树的最近公共祖先,使用c语言实现。
  2. 递归。
  3. 测试环境:Visual Studio 2019。

二、代码展示

精简代码:

struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {
    if(NULL==root||p==root||q==root){//子树置为找到的NULL或p或q
        return root;
    }
    struct TreeNode *left = lowestCommonAncestor(root->left,p,q);//右子树标记
    struct TreeNode *right = lowestCommonAncestor(root->right,p,q);//左子树标记
    if(NULL==left){//左子树为空
        return right;//返回右结点
    }
    if(NULL==right){//右子树为空
        return left;//返回左结点
    }
    return root;//返回符合上述要求的根结点
}//本质是把无关结点置NULL,把路径上有q的结点置q,有p的结点置p。
//最后祖先结点左右分别p、q(顺序无所谓),返回此结点。

完整思路:

struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) {
    if(NULL==root){//越过叶子结点
        return NULL;
    }
    if(p==root||q==root){//子树置为找到的p或q
        return root;
    }
    struct TreeNode *left = lowestCommonAncestor(root->left,p,q);//右子树标记
    struct TreeNode *right = lowestCommonAncestor(root->right,p,q);//左子树标记
    if(NULL==left&&NULL==right){//是叶子结点
        return NULL;
    }
    if(NULL==left){//左子树为空
        return right;//返回右结点
    }
    if(NULL==right){//右子树为空
        return left;//返回左结点
    }
    return root;//返回符合上述要求的根结点
}//源代码的本质是把无关结点置NULL,把路径上有q的结点置q,有p的结点置p,最后祖先结点左右分别p、q,返回此结点。

三、思路分析

  • 二叉树的最近公共祖先。二叉树,考虑递归。
  • 性质一: p p p q q q同时在 r o o t root root左右两边, r o o t root root即是所求
  • 性质二: 如果 q q q r o o t root root左边, r o o t root root右边记录 N U L L NULL NULL。分两种情况;
  1. q q q r o o t root root左子树, p p p不知道在哪。此时记 l e f t = q left = q left=q,弹栈。
  2. p 、 q p、q pq都在 r o o t root root左子树。最近公共祖先一定不是 r o o t root root,但是在 r o o t root root左子树上。
  • q q q r o o t root root右子树,同上。

理解思路很重要!

四、代码分析

  • 代码的本质是把无关结点置 N U L L NULL NULL,把路径上有 q q q的结点置 q q q,有 p p p的结点置 p p p,最后祖先结点左右分别是 p 、 q p、q pq(顺序无所谓)。一直把这个祖先结点传给根结点,此时根结点被染成祖先结点。返回根结点。
  • 这个过程有点像结点在感染结点, N U L L NULL NULL把父节点感染为 N U L L NULL NULL p p p把父节点感染为 p p p q q q把父节点感染为 q q q。直到一个结点左右有 p p p q q q,这个结点就是最近祖先结点。
  • 最近祖先节点不被感染,而是一路把自己向上感染,直到根结点。最后返回根结点,即为所求。

欢迎读者在评论区留言,作为日更博主,看到就会回复的。

五、AC

力扣(LeetCode)236. 二叉树的最近公共祖先(C语言)_第1张图片

六、复杂度分析

  1. 时间复杂度: O ( n ) O(n) O(n) , n n n是树的结点个数,遍历树的时间复杂度是 O ( n ) O(n) O(n)
  2. 空间复杂度: O ( n ) O(n) O(n),递归的空间复杂度,取决于压栈次数,正常树形结构对应平均空间复杂度 O ( l o g n ) O(logn) O(logn)。当树变成类似一条链表,对应最坏空间复杂度 O ( n ) O(n) O(n)

你可能感兴趣的:(小白leetcode,leetcode,c语言,算法,二叉树,深度优先)