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 nodes 5 and 1 is 3.

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 nodes 5 and 4 is 5, 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/

https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/discuss/65225/4-lines-C++JavaPythonRuby

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 236. Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点的更多相关文章

  1. [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 ...

  2. [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 ...

  3. [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 ...

  4. [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 ...

  5. LeetCode 236 Lowest Common Ancestor of a Binary Tree 二叉树两个子节点的最低公共父节点

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...

  6. [leetcode]236. Lowest Common Ancestor of a Binary Tree树的最小公共祖先

    如果一个节点的左右子树上分别有两个节点,那么这棵树是祖先,但是不一定是最小的,但是从下边开始判断,找到后一直返回到上边就是最小的. 如果一个节点的左右子树上只有一个子树上遍历到了节点,那么那个子树可能 ...

  7. 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 ...

  8. 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 ...

  9. (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 ...

随机推荐

  1. 阿里云CentOS7.x安装nodejs及pm2

    对之前文章的修订 您将了解 CentOS下如何安装nodejs CentOS下如何安装NVM CentOS下如何安装git CentOS下如何安装pm2 适用对象 本文档介绍如何在阿里云CentOS系 ...

  2. argparse.ArgumentParser()用法解析

    本博客主要本人学习记录用. 内容来源 于博客:https://blog.csdn.net/the_time_runner/article/details/97941409 argparse模块官方文档 ...

  3. fastadmin表单提交后却没有关闭弹窗

    点击操作按钮弹出窗口,操作完之后提交表单,无论操作成功还是失败,窗口都不关闭,操作之后出现一个笑脸,3秒后回到弹框刚打开的样子 而我们想要的是这个效果: 在jS那里给这个按钮绑定一个事件即可实现

  4. .NET Core 学习笔记之 WebSocketsSample

    1. 服务端 代码如下: Program: using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; namespace WebS ...

  5. Visual Studio Code 小记

    1. 改变语言 如图: 2. 设置皮肤 如图: 3. Visual Studio Code关闭右侧预览功能 4. 关闭预览模式 5. VS Code 优秀的主题 a. Atom One Dark Th ...

  6. kali渗透综合靶机(五)--zico2靶机

    kali渗透综合靶机(五)--zico2靶机 靶机地址:https://www.vulnhub.com/series/zico2,137/#modal210download 一.主机发现 1.netd ...

  7. C# MySQL,Dapper Trans,list

    static async Task MySQLTransDemo() { try { using(dbConnection) { dbConnection.Open(); //The object m ...

  8. C#使用FileSystemWatcher来监控指定文件夹,并使用TCP/IP协议通过Socket发送到另外指定文件夹

    项目需求: 局域网内有两台电脑,电脑A(Windows系统)主要是负责接收一些文件(远程桌面粘贴.FTP上传.文件夹共享等方式),希望能在A接收文件后自动传输到电脑B(Windows系统)来做一个备份 ...

  9. C# 使用Environment获取当前程序运行环境相关信息

    Enviroment类和AppDomain类前者表示系统级的相关信息,后者表示应用程序级的相关信息. 我常用这两个类获取一些程序运行目录.操作系统位数等信息: string basedir = App ...

  10. Android四大组件:BroadcastReceiver 介绍

    介绍 BroadcastReceiver 即广播组件,是 Android 的四大组件之一.用于监听和接收广播消息,并做出响应.有以下一些应用: 不同组件之间的通信(应用内或不同应用之间). 多线程之间 ...