【LeetCode-树】二叉树的最近公共祖先

题目描述#

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

示例:

Copy
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

题目链接: https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/

思路1#

如果一个节点 node 是节点 p 和节点 q 的公共祖先,则 node 和 p、q 满足下面 3 种情况:

  • node->val == p->val,q 在以 node 为根的子树里;
  • node->val == q->val,p 在以 node 为根的子树里;
  • node->val != p->val && node->val != q->val,则 p 在 node 的左子树里且 q 在 node 的右子树里 或者 p 在 node 的右子树里且 q 在 node 的左子树里。

题目要求找到最低的公共祖先,所以我们要遍历树中所有的节点,判断每个节点是否满足条件。下面的代码使用 bfs 遍历。在遍历过程中,越晚遍历意味着节点越深,所以记录满足条件且最晚遍历到的节点作为答案。代码如下:

Copy
/** * 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(root==nullptr) return nullptr; queue<TreeNode*> qq; qq.push(root); TreeNode* ans = nullptr; while(!qq.empty()){ TreeNode* curNode = qq.front(); qq.pop(); if(curNode->val==p->val){ if(search(curNode->left, q) || search(curNode->right, q)) ans = curNode; }else if(curNode->val==q->val){ if(search(curNode->left, p) || search(curNode->right, p)) ans = curNode; }else{ if((search(curNode->left, p)&&search(curNode->right, q)) || (search(curNode->left, q)&&search(curNode->right, p))) ans = curNode; } if(curNode->left!=nullptr) qq.push(curNode->left); if(curNode->right!=nullptr) qq.push(curNode->right); } return ans; } /*在树root中查找是否存在值等于target->val的节点,存在返回true,不存在返回false*/ bool search(TreeNode* root, TreeNode* target){ if(root==nullptr) return false; if(root->val==target->val) return true; return search(root->left, target) || search(root->right, target); } };
  • 时间复杂度:O(n^2)
    n 为节点个数,bfs 遍历需要 O(n),bfs 遍历每一个节点还需要 O(n) 的时间来判断,所以为 O(n^2).
  • 空间复杂度:O(n+h)
    n 为节点个数,h 为树高。

思路2#

换一种思路递归。在 root 的左右子树中寻找 p 或者 q。在左子树中寻找的结果记为 left,在右子树寻找的结果记为 right。如果 left 为空,说明两个节点都在右子树当中:一个节点是右子树的根节点,另一个节点是右子树的子节点,返回 right。同理,如果 right 为空,则返回 left;如果 right 和 left 都不为空,则返回 root。代码如下:

Copy
/** * 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(root==nullptr) return nullptr; if(root==p || root==q) return root; TreeNode* left = lowestCommonAncestor(root->left, p, q); TreeNode* right = lowestCommonAncestor(root->right, p, q); if(left==nullptr) return right; if(right==nullptr) return left; if(left!=nullptr && right!=nullptr) return root; return nullptr; } };
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
posted @   Flix  阅读(165)  评论(0编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥
点击右上角即可分享
微信分享提示
CONTENTS