目录

  • 题目
  • 思考分析
  • 改进

本文章代码思路来源于公众号【代码随想录】

题目

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

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

思考分析

1、自下而上遍历对于此题有极大帮助,而后序遍历的特征便是优先处理叶子结点
2、如何判断一个节点是结点q和结点p的公共祖先:
如果找到一个结点,左子树出现结点p,右子树出现结点q,或者左子树出现结点q,右子树出现结点p。
确定返回值和参数
如果单纯只是告诉我们是否找到结点q或者p,那么返回值为bool就行了。
但是我们还要返回最近公共结点,所以返回值为TreeNode* 类型,如果遇到p或者q,就把p或者q返回,返回值不为空就说明了找到了q或者p。

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)

确定终止条件
如果找到结点p或者结点q或者结点为空,返回

if(root == q || root == p || root == NULL) return root;

确定单层逻辑
首先确定一点我们需要遍历树的所有结点。
直观上讲,如果找到了最近公共祖先,直接一路返回就可以了。如下图

但是事实上还要遍历根结点的右子树(即使现在已经找到了目标结点),这是因为在后序遍历中,如果想要利用left和right做逻辑处理,不能立即返回,而是要等到left和right的逻辑处理完之后才能返回。

left = 递归函数(root->left);
right = 递归函数(root->right);
left 和 right 的逻辑处理

所以我们要遍历整棵树。

TreeNode* left = lowestCommonAncestor(root->left,p,q);
TreeNode* right= lowestCommonAncestor(root->right,p,q);

1、如果left和right都不为空,说明此时root就是最近公共祖先。
2、如果left为空,right不为空,就返回right,说明目标结点是通过right返回的,反之依然。

3、如果left和right都为空,则返回left或者right都是可以的,也就是返回空。

if(left == NULL && right != NULL) return right;
else if(left != NULL && right ==NULL) return left;
else return NULL;       //此时只有left和right同时为空

整个遍历思路:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*///如果一个结点不是另外一个结点的祖先,那么他们的最近祖先的深度一定是深度最小结点的深度-1//如果一个结点是另外一个结点的祖先,那么最近祖先就是是祖先的那个结点。
class Solution {public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL;      //此时只有left和right同时为空}
};

改进

在遍历完左子树之后,若是返回的left不是NULL,也不是p和q,则说明在左子树中已经找到了公共祖先了,此时可以直接返回left的值,无需再遍历右子树。这就是剪枝操作。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*///如果一个结点不是另外一个结点的祖先,那么他们的最近祖先的深度一定是深度最小结点的深度-1//如果一个结点是另外一个结点的祖先,那么最近祖先就是是祖先的那个结点。
class Solution {public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);//*****************剪枝操作******************if(left !=NULL && left !=p && left != q) return left; //*******************************************TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL;       //此时只有left和right同时为空}
};

加入打印信息,对遍历的过程更加了解熟悉;

class Solution {public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == NULL) cout<<"NULL"<<endl;else cout<<root->val<<endl;if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);//*****************剪枝操作******************if(left !=NULL && left !=p && left != q) return left; //*******************************************TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL;     //此时只有left和right同时为空}
};

这一题感觉之后还需要多看几遍,多体会体会,感觉有些地方还是没理解。
若是有新的理解,再更新。

leetcode 236. 二叉树的最近公共祖先 思考分析相关推荐

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

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

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

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

  3. LeetCode 236. 二叉树的最近公共祖先

    文章目录 解法1:保存祖先节点+逐个判断 解法2:深度优先遍历 解法3:记录祖先节点 https://leetcode-cn.com/problems/lowest-common-ancestor-o ...

  4. 最近公共祖先_[LeetCode] 236. 二叉树的最近公共祖先

    题目链接: https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree 难度:中等 通过率:57.2% 题目描述: ...

  5. leetcode 236. 二叉树的最近公共祖先LCA(后序遍历,回溯)

    LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先.百度百科 ...

  6. Leetcode 236.二叉树的最近公共祖先

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

  7. [leetcode]236.二叉树的最近公共祖先

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

  8. LeetCode 236. 二叉树的最近公共祖先(递归)

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

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

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

最新文章

  1. Tesla Model汽车架构与FSD供应链
  2. 大而强 VS 小而美 | 史晓东、周明等共论:大模型主导的时代,NLP 该如何演进?...
  3. Kettle提高表输出写入速度(每秒万条记录)
  4. win 7 系统激活工具
  5. Java网络编程从0——》入门
  6. Pandas的学习(1.pandas的介绍以及pandas中的Series的创建)
  7. 数据在计算机中的存储
  8. Laravel大型项目系列教程(一)
  9. 点播同时并发怎么算带宽_如何搭建一个视频点播系统?
  10. org.attoparser.ParseException: Could not parse as expression: “
  11. 如何使用无线连接来使Android调试手机
  12. 伤感网络验证系统_网络攻防演练中弱密码安全治理的几点建议
  13. 浏览器插件之ActiveX开发(三)
  14. python修改文件名_【Python沙龙】批量修改文件名称
  15. TG电报telegram群发软件,批量采集群成员、发消息、拉人,全自动营销工具,免费用
  16. sps的process插件安装包_Process插件安装及其简单中介分析
  17. 2019年 武汉理工大学计算机考研经验分享
  18. 港科百创 |【香港科大科创产业联盟】正式成立,创始理事相聚第四期科创午餐会...
  19. Html学习1基本的标签(慕课网,Bluefish)
  20. 画彩色斐波那契螺旋线

热门文章

  1. eslint php,ESlint操作步骤详解
  2. React - antd4 中在form中为Switch赋值无效
  3. 深入研究ES6 Generators
  4. box-shadow IE8兼容处理
  5. 行内元素,块级元素,各自特点及其相互转化
  6. safari 音频播放问题
  7. elementUI清空弹框中的表单数据
  8. Java实现并发线程中线程范围内共享数据
  9. leetcode 796. 旋转字符串(Rotate String)
  10. 在Ajax方式产生的浮动框中,点击选项包含某个关键字的选项