LeetCode 热题 100_二叉树的最近公共祖先(49_236_中等_C++)(二叉树;深度优先搜索)
LeetCode 热题 100_二叉树的最近公共祖先(49_236)
- 题目描述:
- 输入输出样例:
- 题解:
- 解题思路:
- 思路一(深度优先搜索):
- 代码实现
- 代码实现(思路一(深度优先搜索)):
- 以思路一为例进行调试
题目描述:
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
输入输出样例:
示例 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 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
提示:
树中节点数目在范围 [2, 105] 内。
-109 <= Node.val <= 109
所有 Node.val 互不相同 。
p != q
p 和 q 均存在于给定的二叉树中。
题解:
解题思路:
思路一(深度优先搜索):
1、在解决此问题时我们首先应该讨论一下p,q在二叉树中的各个分布情况。假设一个结点为root为当前遍历的结点。
递归出口:
① root结点为null则返回(递归出口)(返回null)
② 当前结点为p,返回p(第一次发现p,且未找到q)(返回当前结点,因当前结点可能为祖先)
(为什么直接返回呢,因为我们可以通过遍历除p的子孙节点外的其他结点来判断q的位置:若其他结点中存在q,则p不是q的祖先。若其他结点不存在q,则q是p的子孙,p为公共祖先结点)
③ 当前结点为q,返回q(第一次发现q,且未找到p)(返回当前结点,因当前结点可能为祖先)
(为什么直接返回呢,因为我们可以通过遍历除q的子孙节点外的其他结点来判断p的位置:若其他结点存在p则,q不是p的祖先。若其他结点不存在p,则p是q的子孙,q为公共祖先结点)
递归体: 按深度优先遍历递归的寻找左右子树。
判断当前节点的左右子树(左右子树遍历完后):
① 当前结点左右子树都没有查找到p或q。(返回null)
② 当前结点左子树找到一个结点(p或q),右子树找到一个结点(p或q)。(返回当前结点,当前结点为公共祖先)
③当前结点左子树找到一个结点(p或q),右子树没找到。(返回左子树找到的结点)
④ 当前结点右子树找到一个结点(p或q),左子树没找到。(返回右子树找到的结点)
2、复杂度分析:
① 时间复杂度:O(n),n代表二叉树中结点的个数,最坏的情况会遍历整颗二叉树。
② 空间复杂度:O(n),采用的是深度遍历搜索,所以需要用到函数栈,最坏情况下为O(n)。
代码实现
代码实现(思路一(深度优先搜索)):
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {//遍历到nullptr或者p、 q则返回if (root==nullptr||root==p||root==q) return root;//递归的进行查找TreeNode *left=lowestCommonAncestor(root->left,p,q);TreeNode *right=lowestCommonAncestor(root->right,p,q);//如果当前结点的左右子树都没查找到q或p,则返回nullptrif(left==nullptr&&right==nullptr) return nullptr;//查找到p、q的公共祖先则返回该结点if (left!=nullptr&&right!=nullptr) return root;//p或q存在左子树则返回左子树对应的结点if (left!=nullptr) return left;//p或q存在右子树则返回右子树对应的结点return right;
}
以思路一为例进行调试
#include<iostream>
#include <vector>
#include <queue>
using namespace std;struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};//通过数组创建二叉树,-1代表nullptr;
TreeNode *createTree(vector<int> nums){if (nums.empty()){return nullptr;}queue<TreeNode *> q;TreeNode *root=new TreeNode(nums[0]);q.push(root);int i=1;while (i<nums.size()){TreeNode *node=q.front();q.pop();if (i<nums.size()&&nums[i]!=-1){node->left=new TreeNode(nums[i]);q.push(node->left);}++i;if (i<nums.size()&&nums[i]!=-1){node->right=new TreeNode(nums[i]);q.push(node->right);}++i;}return root;
}//用于检查二叉树是否创建正确
void inorderTraversal(TreeNode *root){if (root==nullptr){return ;}inorderTraversal(root->left);cout<<root->val<<" ";inorderTraversal(root->right);
}//二叉树的最近公共祖先
class Solution
{
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {//遍历到nullptr或者p、 q则返回if (root==nullptr||root==p||root==q) return root;//递归的进行查找TreeNode *left=lowestCommonAncestor(root->left,p,q);TreeNode *right=lowestCommonAncestor(root->right,p,q);//如果当前结点的左右子树都没查找到q或p,则返回nullptrif(left==nullptr&&right==nullptr) return nullptr;//查找到p、q的公共祖先则返回该结点if (left!=nullptr&&right!=nullptr) return root;//p或q存在左子树则返回左子树对应的结点if (left!=nullptr) return left;//p或q存在右子树则返回右子树对应的结点return right; }
};int main(int argc, char const *argv[])
{//-1代表nullvector<int> nums={3,5,1,6,2,0,8,-1,-1,7,4};//通过nums数组创建二叉树TreeNode *root=createTree(nums);//用于检查二叉树是否创建正确//inorderTraversal(root);//计算root->left和root->right的最近公共祖先Solution s;TreeNode *ans = s.lowestCommonAncestor(root,root->left,root->right);cout<<ans->val;return 0;
}
LeetCode 热题 100_二叉树的最近公共祖先(49_236)原题链接
欢迎大家和我沟通交流(✿◠‿◠)
相关文章:
LeetCode 热题 100_二叉树的最近公共祖先(49_236_中等_C++)(二叉树;深度优先搜索)
LeetCode 热题 100_二叉树的最近公共祖先(49_236) 题目描述:输入输出样例:题解:解题思路:思路一(深度优先搜索): 代码实现代码实现(思路一(深度优…...
(三)c#中const、static、readonly的区别
在 C# 中,const、static 和 readonly 都是用来定义不可变的值,但它们有一些关键的区别。让我们详细比较一下这三者的用途和特点: 1. const(常量) 编译时常量:const 用于声明常量,其值必须在编…...
人工智能任务19-基于BERT、ELMO模型对诈骗信息文本进行识别与应用
大家好,我是微学AI,今天给大家介绍一下人工智能任务19-基于BERT、ELMO模型对诈骗信息文本进行识别与应用。近日,演员王星因接到一份看似来自知名公司的拍戏邀约,被骗至泰国并最终被带到缅甸。这一事件迅速引发了社会的广泛关注。该…...
【C++】函数(下)
1、函数的常见样式 常见的函数样式有四种: (1)无参数无返回值 (2)有参数无返回值 (3)无参数有返回值 (4)有参数有返回值 (1)无参数无返回值 示例…...
一个使用 Golang 编写的新一代网络爬虫框架,支持JS动态内容爬取
大家好,今天给大家分享一个由ProjectDiscovery组织开发的开源“下一代爬虫框架”Katana,旨在提供高效、灵活且功能丰富的网络爬取体验,适用于各种自动化管道和数据收集任务。 项目介绍 Katana 是 ProjectDiscovery 精心打造的命令行界面&…...
深入探讨 Vue.js 的动态组件渲染与性能优化
Vue.js 作为一款前端领域中备受欢迎的渐进式框架,以其简单优雅的 API 和灵活性受到开发者的喜爱。在开发复杂应用时,动态组件渲染是一项极其重要的技术,它能够在页面中动态地加载或切换组件,从而显著提升应用的灵活性与用户体验。…...
vulnhub靶场【IA系列】之Tornado
前言 靶机:IA-Tornado,IP地址为192.168.10.11 攻击:kali,IP地址为192.168.10.2 都采用虚拟机,网卡为桥接模式 本文所用靶场、kali镜像以及相关工具,我放置在网盘中,可以复制后面链接查看 htt…...
简要认识JAVAWeb技术三剑客:HTMLCSSJavaScript
目录 一、web标准二、什么是HTML三、什么是CSS四、什么是JavaScript 黑马JAVAWeb飞书在线讲义地址: https://heuqqdmbyk.feishu.cn/wiki/LYVswfK4eigRIhkW0pvcqgH9nWd 一、web标准 Web标准也称网页标准,由一系列的标准组成,大部分由W3C&…...
C# 修改项目类型 应用程序程序改类库
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
卡通风格渲染
1、卡通风格渲染是什么 卡通风格渲染(Cartoon Shading),也称为非真实感渲染(NPR)或卡通渲染(Toon Shading) 主要目的是使3D模型看起来更像手绘的二维卡通或漫画风格,而不是逼真写实…...
ubuntu各分区的用途
在 Ubuntu 中,分区是将硬盘划分为多个逻辑部分的过程,每个分区可以用于不同的用途。合理分区可以提高系统性能、数据安全性和管理效率。以下是 Ubuntu 中常见分区及其用途的详细说明: 1. 根分区 (/) 用途:存放操作系统核心文件、…...
理解STC15F2K60S2单片机的最小电路
一、STC15F2K60S2与51单片机的区别 STC15F2K60S2和51单片机虽然都基于8051内核,但在多个方面存在显著区别: 1. CPU性能: - STC15F2K60S2:采用增强型8051 CPU,1T单时钟/机器周期,速度比普通8051快8-12倍…...
Docker官网安装
1.官网 官方文档 https://www.docker.com/ Docker Hub官网 镜像 https://hub.docker.com/ 2.Docker 的三要素 1、镜像 2、容器 3、仓库 小总结 3.Docker 平台架构图 (架构版本) 4.安装Docker CentOS | Docker Docs 1.确定你是CentOS7及以上版本 …...
成功案例分享 — 芯科科技助力涂鸦智能打造Matter over Thread模块,简化Matter设备开发
芯科科技(Silicon Labs)的愿景之一是让开发者每天都能够更轻松地开发无线物联网(IoT)。特别是在拥有相同愿景的合作伙伴的帮助下,我们每天都在取得进步。但是要想弥合知识水平和物联网开发之间的差距仍会面临一定的挑战…...
基于Python机器学习、深度学习技术提升气象、海洋、水文领域实践应用-以ENSO预测为例讲解
1. 背景与目标 ENSO(El Nio-Southern Oscillation)是全球气候系统中最显著的年际变率现象之一,对全球气候、农业、渔业等有着深远的影响。准确预测ENSO事件的发生和发展对于减灾防灾具有重要意义。近年来,深度学习技术在气象领域…...
【Rust自学】12.6. 使用TDD(测试驱动开发)开发库功能
12.6.0. 写在正文之前 第12章要做一个实例的项目——一个命令行程序。这个程序是一个grep(Global Regular Expression Print),是一个全局正则搜索和输出的工具。它的功能是在指定的文件中搜索出指定的文字。 这个项目分为这么几步: 接收命令行参数读取…...
贪心算法汇总
1.贪心算法 贪心的本质是选择每一阶段的局部最优,从而达到全局最优。 如何能看出局部最优是否能推出整体最优 靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。 如何验证可不可以…...
H266/VVC 帧内预测中 ISP 技术
帧内子划分 ISP ISP 技术是在 JVET-2002-v3 提案中详细介绍其原理,在 VTM8 中完整展示算法。ISP是线基内预测(LIP)模式的更新版本,它改善了原始方法在编码增益和复杂度之间的权衡,ISP 算法的核心原理就是利用较近的像…...
PyTorch 中的 Dropout 解析
文章目录 一、Dropout 的核心作用数值示例:置零与缩放**训练阶段****推理阶段** 二、Dropout 的最佳使用位置与具体实例解析1. 放在全连接层后2. 卷积层后的使用考量3. BatchNorm 层与 Dropout 的关系4. Transformer 中的 Dropout 应用 三、如何确定 Dropout 的位置…...
集中式架构vs分布式架构
一、集中式架构 如何准确理解集中式架构 1. 集中式架构的定义 集中式架构是一种将系统的所有计算、存储、数据处理和控制逻辑集中在一个或少数几个节点上运行的架构模式。这些中央节点(服务器或主机)作为系统的核心,负责处理所有用户请求和…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
