LeetCode 面试题 04.08. 首个共同祖先

2023-09-13 19:44:59

一、题目

  设计并实现一个算法,找出二叉树中某两个节点的第一个共同祖先。不得将其他的节点存储在另外的数据结构中。注意:这不一定是二叉搜索树。

  例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

    3
   / \
  5   1
 / \ / \
6  2 0  8
  / \
 7   4

  点击此处跳转题目

示例 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。因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。

二、C# 题解

  基本思路为,后序遍历该树,即先访问孩子结点,后访问该结点,因此为自底向上遍历,处理该结点时就已知左右子树的结果。具体情况对应的处理如下:

   node
  /    \
left  right
  1. node 为 null:返回 null;
  2. node 为 p 或 q:
    1. 若 left、right 中也有一个为 p 或 q:表示该树已找到 p 和 q,返回 node 并标识已找到;
    2. left、right 均不为 p 或 q:表示第一个找到,返回 node 自己即可;
  3. node 不为 p 或 q:
    1. left、right 均为 p 或 q:表示该树已找到 p 和 q,返回 node 并标识已找到;
    2. left 为 p 或 q 而 right 不是:返回 left,表示该树找只到了一个;
    3. right 为 p 或 q 而 left 不是:返回 right,表示该树找只到了一个;
    4. left、right 均不为 p 或 q:返回 null,表示没找到。
  4. 如果标识出子树已找到结果,则直接返回 left、right 中不为 null 的那一个,那个就记录了第一个共同父亲。
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        bool rt = false;
        return Partition(root, p, q, ref rt);
    }

    // DFS 递归,bool rt 用于记录是否已同时找到 p、q
    public TreeNode Partition(TreeNode node, TreeNode p, TreeNode q, ref bool rt) {
        if (node == null) return null;     // 情况 1

        TreeNode left = Partition(node.left, p, q, ref rt);   // 左子树结果
        TreeNode right = Partition(node.right, p, q, ref rt); // 右子树结果

        if (rt) return left == null ? right : left; // 已找到结果,即情况 4

        // 没找到结果,分为以下几种情况
        TreeNode result = null;
        if (node == p || node == q) {      // 情况 2
            if (left == p || left == q || right == p || right == q) rt = true; // 情况 2.1
            result = node;                 // 返回结果为自己
        }
        else if (left == p || left == q) { 
            if (right == p || right == q)  // 情况 3.1
            	{ rt = true; result = node; } 
            else result = left;            // 情况 3.2
        }
        else if (right == p || right == q) // 情况 3.3
            result = right;

        return result;                     // 情况 3.4
    }
}
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)
更多推荐

PCIE基础知识-3

PCIE三种传输方式:IO中断,DMA,peertopeer中断:PCI设备需要向内存(SDRAM)中写入一些数据,该PCI设备会向CPU请求一个中断,然后CPU首先先通过PCI总线把该PCI设备的数据读取到CPU内部的寄存器中,然后再把数据从内部寄存器写入到内存(SDRAM)中。DMA:直接内存访问(DMA,Dire

​CVPR 2023 | STAR Loss:减少人脸关键点标注歧义,实现人脸关键点SOTA精度

论文链接:https://arxiv.org/pdf/2306.02763.pdf代码链接:https://github.com/ZhenglinZhou/STAR要解决的问题:人脸关键点检测标注中存在语义歧义问题。语义歧义是指不同的标注者对同一个面部特征点的位置有不同的理解,导致标注结果不一致,影响模型的收敛和准确性

设计模式-代理模式

“阁下有什么问题可以和我的代理律师谈即可”,为什么会有律师这个职业呢?随着法律法规的逐步完善,日益复杂,导致大部分的普通民众掌握的法律知识明显不足,进而无法在合适的时间点进行维权、规避风险。可见,律师的作用就是利用自身的专业知识帮助案件当事人处理其无法处理的事情。不仅只有律师,生活中处处可见这种代理模式的存在,比如婚庆

麦肯锡:中国生成式AI市场现状和未来发展趋势

本文来自《麦肯锡中国金融业CEO季刊》,版权归麦肯锡所有。该季刊主要围绕生成式AI(以下简称“GenAI”)主题,通过4大章节共8篇文章,全面深入分析了GenAI对各主要行业的影响、价值链投资机会、中国GenAI市场现状和未来趋势以及企业如何布局GenAI,从而真正挖掘其价值。随着ChatGPT的火爆出圈,GenAI成

2023年8月京东空调行业品牌销售排行榜(京东数据报告)

鲸参谋监测的京东平台8月份空调市场销售数据已出炉!鲸参谋数据显示,今年8月份,京东平台上空调的销量将近146万,环比降低约44%,同比降低约37%;销售额为41亿+,环比下降约45%,同比下降约40%。可以看到,8月份空调市场整体下滑。*数据源于鲸参谋-行业趋势分析(来自公开渠道获取,数据仅供参考)空调市场中,格力品牌

Python编程指南:利用HTTP和HTTPS适配器实现智能路由

目录HTTP和HTTPS适配器什么是智能路由利用HTTP和HTTPS适配器实现智能路由总结在Python编程中,利用HTTP和HTTPS适配器实现智能路由是一项非常实用的技能。智能路由可以根据不同的条件选择不同的路由,从而提高网络性能和用户体验。在本文中,我们将介绍如何使用Python编程语言和HTTP/HTTPS适配

非对称加密、解密原理及openssl中的RSA示例代码

一、【原理简介】非对称加密非对称加密,也被称为公钥加密,其中使用一对相关的密钥:一个公钥和一个私钥。公钥用于加密数据,私钥用于解密数据。公钥可以公开分享,而私钥必须保密。密钥生成:当一个用户或设备希望使用非对称加密时,要生成一对密钥:一个公钥和一个私钥。这两个密钥是数学上相关的,但从公钥中计算出私钥在计算上是不可行的。

【操作系统笔记】内存寻址

物理寻址主存(内存)计算机主存也可以称为物理内存,内存可以看成由若干个连续字节大小的单元组成的数组每个字节都有一个唯一的物理地址(PhysicalAddress)CPU访问内存前,先拿到内存地址,然后,通过内存地址访问内存中数据指令总线的分工数据总线:负责传输实际数据的地址总线:负责传输数据地址的,用来确定到底把数据传

FPGA千兆网 UDP 网络视频传输,基于88E1518 PHY实现,提供工程和QT上位机源码加技术支持

目录1、前言版本更新说明免责声明2、我这里已有的以太网方案3、设计思路框架视频源选择OV5640摄像头配置及采集动态彩条UDP协议栈UDP视频数据组包UDP协议栈数据发送UDP协议栈数据缓冲IP地址、端口号的修改TriModeEthernetMAC介绍以及移植注意事项88E1518PHYQT上位机和源码4、vivado

AOSP源码中Android.mk文件中的反斜杠符号(\)的作用和使用

简介在AOSP(AndroidOpenSourceProject)源码中的Android.mk文件中,反斜杠符号(\)的主要作用是将一行代码拆分成多行,以提高可读性并帮助组织较长的代码块。这对于定义复杂的构建规则和变量时特别有用。以下是\符号在Android.mk文件中的作用以及如何使用它的示例:多行命令:Androi

Nacos使用教程(三)——nacos注册中心(2)

文章目录什么是注册中心注册中心的作用1.服务注册2.服务发现3.负载均衡4.故障恢复注册中心的解决的问题1.服务管理问题2.服务调用问题3.负载均衡问题4.故障恢复问题服务的发现与注册的实现模式服务注册表Nacos注册中心的部署与使用什么是Nacos注册中心Nacos注册中心的部署下载Nacos安装包解压安装包修改配置

热文推荐