[LeetCode] 236. Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes5
and1
is3.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes5
and4
is5
, since a node can be a descendant of itself according to the LCA definition.
Note:
- All of the nodes' values will be unique.
- p and q are different and both values will exist in the binary tree.
这道求二叉树的最小共同父节点的题是之前那道 Lowest Common Ancestor of a Binary Search Tree 的 Follow Up。跟之前那题不同的地方是,这道题是普通是二叉树,不是二叉搜索树,所以就不能利用其特有的性质,我们只能在二叉树中来搜索p和q,然后从路径中找到最后一个相同的节点即为父节点,可以用递归来实现,在递归函数中,首先看当前结点是否为空,若为空则直接返回空,若为p或q中的任意一个,也直接返回当前结点。否则的话就对其左右子结点分别调用递归函数,由于这道题限制了p和q一定都在二叉树中存在,那么如果当前结点不等于p或q,p和q要么分别位于左右子树中,要么同时位于左子树,或者同时位于右子树,那么我们分别来讨论:
- 若p和q分别位于左右子树中,那么对左右子结点调用递归函数,会分别返回p和q结点的位置,而当前结点正好就是p和q的最小共同父结点,直接返回当前结点即可,这就是题目中的例子1的情况。
- 若p和q同时位于左子树,这里有两种情况,一种情况是 left 会返回p和q中较高的那个位置,而 right 会返回空,所以最终返回非空的 left 即可,这就是题目中的例子2的情况。还有一种情况是会返回p和q的最小父结点,就是说当前结点的左子树中的某个结点才是p和q的最小父结点,会被返回。
- 若p和q同时位于右子树,同样这里有两种情况,一种情况是 right 会返回p和q中较高的那个位置,而 left 会返回空,所以最终返回非空的 right 即可,还有一种情况是会返回p和q的最小父结点,就是说当前结点的右子树中的某个结点才是p和q的最小父结点,会被返回,写法很简洁,代码如下:
解法一:
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || p == root || q == root) return root;
TreeNode *left = lowestCommonAncestor(root->left, p, q);
TreeNode *right = lowestCommonAncestor(root->right, p , q);
if (left && right) return root;
return left ? left : right;
}
};
上述代码可以进行优化一下,如果当前结点不为空,且既不是p也不是q,那么根据上面的分析,p和q的位置就有三种情况,p和q要么分别位于左右子树中,要么同时位于左子树,或者同时位于右子树。我们需要优化的情况就是当p和q同时为于左子树或右子树中,而且返回的结点并不是p或q,那么就是p和q的最小父结点了,已经求出来了,就不用再对右结点调用递归函数了,这是为啥呢?因为根本不会存在 left 既不是p也不是q,同时还有p或者q在 right 中。首先递归的第一句就限定了只要遇到了p或者q,就直接返回,之后又限定了只有当 left 和 right 同时存在的时候,才会返回当前结点,当前结点若不是p或q,则一定是最小父节点,否则 left 一定是p或者q。这里的逻辑比较绕,不太好想,多想想应该可以理清头绪吧,参见代码如下:
解法二:
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || p == root || q == root) return root;
TreeNode *left = lowestCommonAncestor(root->left, p, q);
if (left && left != p && left != q) return left;
TreeNode *right = lowestCommonAncestor(root->right, p , q);
if (left && right) return root;
return left ? left : right;
}
};
讨论:此题还有一种情况,题目中没有明确说明p和q是否是树中的节点,如果不是,应该返回 nullptr,而上面的方法就不正确了,对于这种情况请参见 Cracking the Coding Interview 5th Edition 的第 233-234 页。
Github 同步地址:
https://github.com/grandyang/leetcode/issues/236
类似题目:
Lowest Common Ancestor of a Binary Search Tree
参考资料:
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 236. Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点的更多相关文章
- [LeetCode] Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- [LeetCode] 236. Lowest Common Ancestor of a Binary Tree 二叉树的最近公共祖先
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- [leetcode]236. Lowest Common Ancestor of a Binary Tree二叉树最近公共祖先
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. Accordi ...
- [leetcode]236. Lowest Common Ancestor of a Binary Tree 二叉树最低公共父节点
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- LeetCode 236 Lowest Common Ancestor of a Binary Tree 二叉树两个子节点的最低公共父节点
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...
- [leetcode]236. Lowest Common Ancestor of a Binary Tree树的最小公共祖先
如果一个节点的左右子树上分别有两个节点,那么这棵树是祖先,但是不一定是最小的,但是从下边开始判断,找到后一直返回到上边就是最小的. 如果一个节点的左右子树上只有一个子树上遍历到了节点,那么那个子树可能 ...
- leetcode@ [236] Lowest Common Ancestor of a Binary Tree(Tree)
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/ Given a binary tree, find the ...
- leetcode 236. Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- (medium)LeetCode 236.Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
随机推荐
- 怎么做web接口测试
这就需要开发提供的接口文档了,接口文档和功能测试的需求说明书的功能是一样的.包括:接口说明.调用的url,请求方式(get or post),请求参数.参数类型.请求参数说明,返回结果说明.有 ...
- Quartz的配置与使用
什么是Quartz Quartz是OpenSymphony开源组织在Job scheduling领域的开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为 ...
- 从零开始实现放置游戏(六)——实现后台管理系统(4)Excel批量导入
前面我们已经实现了在后台管理系统中,对配置数据的增删查改.但每次添加只能添加一条数据,实际生产中,大量数据通过手工一条一条添加不太现实.本章我们就实现通过Excel导入配置数据的功能.这里我们还是以地 ...
- 一款常用的截图工具(能够截gif动图)
这款工具用来截程序的演示GIF图片,灰常方便. 直接上Github地址: https://github.com/NickeManarin/ScreenToGif
- WInforn中设置ZedGraph的焦点显示坐标格式化以及显示三个坐标数的解决办法
场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...
- Flask--g属性
目录 Flask之g属性 使用 session,flash,g的区别 Flask之g属性 专门用来存储用户信息的g对象,g的全称的为global g对象在一次请求中的所有的代码的地方,都是可以使用的 ...
- 【设计模式】Singleton
前言 Singleton设计模式,确保全局只存在一个该类的实例.将构造器声明为private,防止调用(虽然还是可以使用反射来调用).声明一个静态的类实例在类中,声明一个公共的获取实例的方法.这篇博文 ...
- Vim操作:打开文件
1.打开文件并定位到某一行 vim +20 vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php # 定位至第20行 2 ...
- EM算法-完整推导
前篇已经对EM过程,举了扔硬币和高斯分布等案例来直观认识了, 目标是参数估计, 分为 E-step 和 M-step, 不断循环, 直到收敛则求出了近似的估计参数, 不多说了, 本篇不说栗子, 直接来 ...
- SpringBoot使用Hibernate,实现自动创建数据库表【博客数据库设计】
我们准备设计博客,那就要设计数据库. 我们可以使用Hibernate来自动生成数据库. 博客数据库的结构: 实体类: 博客 Blog 博客分类 Type 博客标签 Tag 博客评论 Comment 用 ...