力扣

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 1:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:

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

输入:root = [1,2], p = 1, q = 2
输出:1

提示:

树中节点数目在范围 [2, 105] 内。
-109 <= Node.val <= 109
所有 Node.val 互不相同 。
p != q
p 和 q 均存在于给定的二叉树中。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一个节点也可以是自己的祖先。

沿着根节点到当前结点的路径上的所有的结点都可以是自己的祖先

如果这里是三叉链,结点带parent,转换成链表相交的做法就可以了,

但是很可惜,这里并不是三叉链

规则:一个是左子树中的结点,一个是右子树中的结点,那么他就是最近公共祖先

1.如果这两个结点在我的左子树和右子树当中,那么我就是这两个结点的最近公共祖先

2.如果这两个结点都在我的左边,那么我就去查找我的左子树是不是最近公共祖先

3.如果这两个结点都在我的右边,那么我就去查找我的右子树是不是最近公共祖先

4.如果我就是其中的一个要查找的结点,另外一个结点是我的孩子,那么我就是最近公共祖先

/*** 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:bool Find(TreeNode* sub,TreeNode* x){if(sub==nullptr){return false;}if(sub==x){return true;}//去当前结点的左子树去找x,或者去右子树去找x,只要有一个地方找到就行return Find(sub->left,x)||Find(sub->right,x);}// 如果这两个结点在我的左子树和右子树当中,那么我就是这两个结点的最近公共祖先// 如果这两个结点都在我的左边,那么我就去查找我的左子树是不是最近公共祖先// 如果这两个结点都在我的右边,那么我就去查找我的右子树是不是最近公共祖先TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root==nullptr)return nullptr;// 如果我就是其中的一个要查找的结点,另外一个结点是我的孩子,那么我就是最近公共祖先if(root==p||root==q)return root;bool p_In_Left,p_In_Right,q_In_Left,q_InRight;//到我当前结点的左子树中去寻找p,如果找到了,就不要再往右子树当中找了p_In_Left=Find(root->left,p);//如果p在左边,那么就一定不在右边//因为我们的p一定在这棵树里面p_In_Right=!p_In_Left;//如果q在左边,那么就一定不在右边//因为我们的q一定在这棵树里面q_In_Left=Find(root->left,q);q_InRight=!q_In_Left;//1、一个在左,一个在右,那么root就是最近公共祖先//2、如果都在左,那么递归去左子树找//3、如果都在右,那么递归去右子树找if((p_In_Left&&q_InRight)||(q_In_Left&&p_In_Right)){return root;}//2、如果都在左,那么递归去左子树找else if(p_In_Left&&q_In_Left){return lowestCommonAncestor(root->left, p,q);}//3、如果都在右,那么递归去右子树找else if(p_In_Right&&q_InRight){return lowestCommonAncestor(root->right, p,q);}else{//理论而言,不会走这里。return nullptr;}}
};

如果我们的要查找的两个结点越在我们的树的下面的结点,我们的上面这种算法的时间和空间开销就越大。

这里的find的时间复杂度就是O(N)

最多要找二叉树高度次(H)

也就是时间复杂度为O(N*H)

如果这里是一棵搜索二叉树,也就是左子树比根节点小,右子树比根节点都打,那我们就不需要这里的find函数了,也就可以提升我们的效率了。

如何从O(N*H)优化到O(N),

如果我们这道题能够找到根节点到目标节点的路径,那么我们就能够转换为链表相交的方法去做了。现在我们就可以尝试寻找这两条路径

(这里我们按照前序遍历)

如果我们这里寻找6,当前我们的根节点,

3不是6,入栈3

5不是6,5入栈

6是6,找到了,再层层返回出栈

如果我们现在要找4,

3不是4,入栈4

5不是4,入栈5

6不是4,入栈6

6的左右都是nullptr,都返回的是false

此时我们可以确定6这棵子树下面没有我们的目标结点了,将6出栈

接着2不是4,入栈2

7不是4,入栈2

7的左右结点都是nullptr,返回都是false

此时我们可以确定7这棵子树下面没有我们的目标节点了,将7出栈

4是我们的要找的结点,返回true,停止查找。

/*** 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:bool FindPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& path){//这里返回的false和true都是提供给上一层的。if(root==nullptr)return false;path.push(root);if(root==x)return true;//左树找到了,右树就不要找了if(FindPath(root->left,x,path))return true;//左树没找到,就再去右树找if(FindPath(root->right,x,path))return true;//左树和右树都没有找到path.pop();//这里的false代表当前子树里面没有我们想要查找的结点return false;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {//创建两个栈用于存储从根节点到目标节点的路径stack<TreeNode*> pPath,qPath;FindPath(root,p,pPath);FindPath(root,q,qPath);//类似链表相交//让长的先走while(pPath.size()!=qPath.size()){//我们的栈刚好是反着存的,也就是树的底部的结点存在栈的顶部,root结点在栈的底部if(pPath.size()>qPath.size())pPath.pop();elseqPath.pop();}while(pPath.top()!=qPath.top()){pPath.pop();qPath.pop();}//这两个路径是一定会有交点的//这里返回pPath或者qPath的top都是可以的。return pPath.top();}
};

这一种思路就是将我们的时间复杂度降低到了O(N),也就是最多遍历一遍二叉树的所有结点。并且我们这一种方法相较于我们的上一种方法,由于我们这里开辟了两个栈,所以空间复杂度比较大。

【LeetCode】【二叉树的最近公共祖先】相关推荐

  1. LeetCode——二叉树的最近公共祖先

    此问题也成为LCA问题 题目描述: 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个节点 p.q,最近公共祖先表示为一个节点 ...

  2. LeetCode 1676. 二叉树的最近公共祖先 IV

    文章目录 1. 题目 2. 解题 1. 题目 给定一棵二叉树的根节点 root 和 TreeNode 类对象的数组(列表) nodes,返回 nodes 中所有节点的最近公共祖先(LCA). 数组(列 ...

  3. 【LeetCode】【HOT】236. 二叉树的最近公共祖先(递归)

    [LeetCode][HOT]236. 二叉树的最近公共祖先 文章目录 [LeetCode][HOT]236. 二叉树的最近公共祖先 package hot;class TreeNode{int va ...

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

    [LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 文章目录 [LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 一.DFS 一.DFS 祖先的定义 ...

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

    一.环境说明 本文是 LeetCode 236. 二叉树的最近公共祖先,使用c语言实现. 递归. 测试环境:Visual Studio 2019. 二.代码展示 精简代码: struct TreeNo ...

  6. LeetCode二叉树系列——236.二叉树的最近公共祖先

    一.题目描述: 236. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个节点 p.q,最近公共祖先表 ...

  7. leetcode 236. 二叉树的最近公共祖先 递归解法 c语言

    如题: 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先.百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x, 满足 x 是 p.q ...

  8. 最近公共祖先_leetcode No.236 二叉树的最近公共祖先

    承接二叉搜索树的最近公共祖先. 题目链接: 二叉树的最近公共祖先 - 力扣(LeetCode)​leetcode-cn.com 题目描述: 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百 ...

  9. 奇安信集团笔试题:二叉树的最近公共祖先(leetcode236),杀死进程(leetcode582)...

    1. 二叉树最近公共祖先 奇安信集团 2020校招 服务端开发-应用开发方向在线考试 编程题|20分2/2 寻祖问宗 时间限制:C/C++语言 1000MS:其他语言 3000MS 内存限制:C/C+ ...

  10. 代码随想录算法训练营第22天 二叉树 java :235. 二叉树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

    文章目录 LeetCode 236. 二叉树的最近公共祖先 题目讲解 思路 LeetCode 701.二叉搜索树中的插入操作 题目讲解 思路 LeetCode 450.删除二叉搜索树中的节点 题目讲解 ...

最新文章

  1. “比特币耶稣”Roger Ver:比特币现金分叉没有技术论据支持
  2. 数据表操作(DQL)
  3. 一篇来自前端同学对后端接口的吐槽
  4. ip地址转换pta题目_PTA「实验2-3-5 输出华氏-摄氏温度转换表」
  5. Java8 新特性 Optional
  6. 惹恼程序员的10件事
  7. [转帖]Windows7 结束更新 以及后期更新花费。
  8. 【 Codeforces Round #547 (Div. 3) F2】Same Sum Blocks (Hard)【思维贪心】
  9. LINUX移植——内核移植(一)
  10. 驱动人生病毒清除教程
  11. oracle建表唯一约束语句,oracle 详细建表语句
  12. Zemax简单透镜的设计与优化
  13. Windows使用Dism备份操作系统快捷命令 系统备份
  14. 《活出生命的意义》读书笔记
  15. 计算机vb里代码里的双引号,在VB中使用字符串中的左双引号
  16. HTML观鸟网小练习
  17. 转:长篇小说《七月七日晴》(超感人的)(上)
  18. 函数——哥德巴赫猜想
  19. SVPWM控制技术+Matlab/Simulink仿真详解
  20. 三棱锥内切球半径求法

热门文章

  1. 六、【s3c2440移植u-boot-2016-11】 优化
  2. 电脑提示vcomp140.dll无法继续执行代码
  3. 上班族健身小白如何锻炼身体,做力量训练
  4. BLE 蓝牙 与APP 得交互 内设 外设
  5. let/const相关内容(五)
  6. 智慧商贸系统-收支管理新增
  7. 修改并编译OpenCV源码提升霍夫变换线检测效果
  8. 什么是信息安全服务资质
  9. 易语言 设置屏幕刷新率 源码_iQOO 5 Pro智能手机屏幕测评报告 「Soomal」
  10. 人工智能与机器学习课程设计