236. Lowest Common Ancestor of a Binary Tree Medium

https://leetcode.com/problems/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 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.

分析:

首先,树的问题,往往涉及递归,之所以涉及递归是因为每一棵树都是由相同结构的多个子树构成。本题可以利用递归的方式,相当于从叶子节点开始,递归地返回如下信息:当前树(或子树)同时包含p和q,则函数返回的结果就是它们的最低公共祖先。如果它们其中之一在子树当中,则结果是它们中的一个。如果它们都不在子树里,则结果返回NULL。

class Solution {
public:
TreeNode * lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 虽然下面两个if可以写到一起,但所表达的意思是不一样的
if (root == nullptr) {
return nullptr;
}
if (p == root || q == root) {
return root;
}
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (left == nullptr) { // 如果有一个分支为空,另一个不为空,则返回不为空的节点
return right;
}
else if (right == nullptr) {
return left;
}
else // 如果两个都不为空,则返回二者当前最低祖先节点
return root;
}
};

总结:

书上对这道题的做法麻烦了。首先书上并不是二叉树,而是一颗普通树,所以next存在一个vector里。
其次,书上的做法是先找到p和q两条路径,从根节点出发到p和q分别构成两条链表;
最后,寻找这两条链表的第一个分叉的地方。

注:

如果本题的树是二叉搜索树或者有指向父节点的指针,则思路能更加简单。

1)如果是二叉搜索树,我们只需要从树的根节点开始和两个输入节点进行比较,如果当前节点的值比两个节点的值都大,那么最低的共同父节点一定在当前节点的左子树中,于是下一步遍历当前节点的左子节点;反之,则遍历右子节点。这样,在树中从上到下找到的第一个在两个输入节点的值之间的节点就是最低公共祖先。

2)如果是一棵普通的树,但有指向父节点的指针,此时问题可以换成求两个链表的第一个公共节点。

3)书上面试者提供的从上至下遍历子树的思路相同,其实并不好,因为会涉及到某些结点的多次遍历,一方面我觉得可以利用类似动态规划的方法存储不同节点的遍历结果信息(如用一个字典),下次再用到的时候直接返回结果即可。另一方面,和面试者提出的优化方法一样,利用辅助空间,将从根节点到输入的两个节点的路径分别用两个链表保存,然后将问题转化为两个链表最后公共节点(和注释2类似)。链表的实现用的是C++ list,如:list<TreeNode*> path1。本题是另一种优化思路,自底向上这样避免了多次遍历相同节点,保证了每个节点只遍历一次。(有一种动态规划的思想)

书上思路如下:

面试者是这么解释这个思路的:所谓两个节点的公共祖先,指的是这两个节点都出现在某个节点的子树中。我们可以从根节点开始遍历一棵树,每遍历到一个节点时,判断两个输入节点是不是在它的子树中。如果在子树中,则分别遍历它的所有子节点,并判断两个输入节点是不是在它们的子树中。这样从上到下一直找到的第一个节点,它自己的子树同时包含两个输入的节点而它的子节点却没有,那么该节点就是最低公共祖先。

Leetcode之236. Lowest Common Ancestor of a Binary Tree Medium的更多相关文章

  1. 【LeetCode】236. Lowest Common Ancestor of a Binary Tree 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  2. 【LeetCode】236. Lowest Common Ancestor of a Binary Tree

    Lowest Common Ancestor of a Binary Tree Given a binary tree, find the lowest common ancestor (LCA) o ...

  3. 【刷题-LeetCode】236. Lowest Common Ancestor of a Binary Tree

    Lowest Common Ancestor of a Binary Tree Given a binary tree, find the lowest common ancestor (LCA) o ...

  4. LeetCode OJ 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 235. Lowest Common Ancestor of a Binary Search Tree 236. Lowest Common Ancestor of a Binary Tree

    https://www.cnblogs.com/grandyang/p/4641968.html http://www.cnblogs.com/grandyang/p/4640572.html 利用二 ...

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

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

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

  9. 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. vue3.0脚手架 创建项目

    1.下载node最新稳定版本,并且安装 2.安装好之后,在cmd或者terminal下, 使用npm -v 查看当前npm版本,验证是否安装成功 3.安装成功后,运行 npm i -g @vue/cl ...

  2. Excle导出优化(poi)

    搜索词条 1.idea报java.lang.OutOfMemoryError: Java heap space怎么解决? 2.java.lang.OutOfMemoryError: GC overhe ...

  3. 快速搭建FTP服务器

    快速搭建一个本地的FTP服务器  如果需要开发FTP文件上传下载功能,那么需要在本机上搭建一个本地FTP服务器,方便调试.第一步:配置IIS Web服务器1.1 控制面板中找到“程序”并打开 1.2 ...

  4. validatebox自定义验证规则以及使用

    //===============jsp======state==== //开启验证 <script  type="text/javascript"> ​​​​​​​y ...

  5. 优化编辑器的编程语言 mlton

    MLton 是整个程序的优化编译器的标准ML编程语言.

  6. process 请求数据解析问题

    开发过程中发现ajax提交的数据无法被express正确的解析,主要的情况是这样的: // 浏览器端post一个对象 $.ajax({ url:"/save", type:&quo ...

  7. 003_FREERTOS任务基础知识

    (一)任务状态 FreeRTOS 中的任务永远处于下面几个状态中的某一个: ● 运行态当一个任务正在运行时,那么就说这个任务处于运行态,处于运行态的任务就是当前正在使用处理器的任务.如果使用的是单核处 ...

  8. springboot+mvc+mbatisplus

    https://www.cnblogs.com/scode2/p/8718553.html

  9. 使用harborv1.8.0-rc1 搭建docker私有镜像仓库

    概述 搭建一个私有仓库 harbor介绍 harbor是一个开源的docker容器仓库,由下面几个组件组成 + proxy:用来接收docker客户端和浏览器端的请求,并且把请求转发给后端的服务 + ...

  10. 转义字符\'和\"的使用示例

    /* 转义字符\'和\"的使用示例 */ #include <stdio.h> int main(void) { printf("关于字符串常量和字符常量.\n&quo ...