Leetcode 236.二叉树的最近公共祖先

题目描述

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例一:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 

 示例二:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 因为根据定义最近公共祖先节点可以为节点本身。

示例三:

 

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 6, q = 2
输出:3
解释:节点 6和节点 2的最近公共祖先是节点 5

示例四: 

输入:root = [1,2], p = 1, q = 2
输出:1

 这道题同样是一道经典的二叉树题目,具有很好的启发性和很好的递归价值,类似于找交点,但该题的难点

第一在于这颗二叉树是乱序的,不是搜索二叉树,不能通过判断值的大小来剪枝确定方向,而且题目给的是指针不能通过值的比较来查找节点同时不能排除一颗树中出现两个值相同的节点,也无法直接通过值的比较来查找。

第二在于树形结构没有parent父节点,所以我们无法在遍历的时候无法通过回溯知晓它的路径。

所以理论上只要解决或能规避以上两个问题,然后找出两个节点往前第一个共同的父节点就是最近的父节点了,结合题目来看有三种情况:

1、两个节点一个root的左子树,一个在右子树,这种情况下,最近的公共祖先就只能是根节点。

2、两个节点都在左或者都在根节点右或是都在左,最麻烦的情况,需要确定路径然后找出最近的公共祖先。

3、一个节点是另一个节点的祖先,直接返回该节点。

方法一:暴力搜索

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:
//判断该路径中是否有目标节点,用于确定目标节点是在root的左还是右bool Istree(TreeNode* root,TreeNode* cur){if(root==nullptr)return false;return root==cur||Istree(root->left,cur)||Istree(root->right,cur);//最终只要返回true就证明目标节点在此路径下}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root==nullptr)//根为空直接返回return nullptr;if(root==p||root==q)//有一个是根节点就直接返回return root;//这里变量的创建是之后理清思路的关键,四个变量,p是否在左or右,q是否在左or右bool pleft,pright,qleft,qright;   pleft=Istree(root->left,p);//如果p在root左边就为true,不在就为falsepright=!pleft;//直接和上面取反,如果在左那一定不在右,反之一定在右qleft=Istree(root->left,q);qright=!qleft;if((pleft&&qright)||(qleft&&pright))//如果一个在左一个在右直接返回root{return root;}else if(pleft&&qleft)//如果都在左直接去root的左边找{return lowestCommonAncestor(root->left,p,q);}else//如果在右直接去root右边找{return lowestCommonAncestor(root->right,p,q);}}
};

方法二:用stack 来记录和删除路径最后找出公共祖先

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public://结合stack前序遍历bool Istree(TreeNode* root,TreeNode* cur,stack<TreeNode*> &arr){if(root==nullptr)//为空直接返回falsereturn false;arr.push(root);//先插入该节点然后去它的左右子树找,如果没找到最后pop掉if(cur==root)//找到目标节点返回truereturn true;if(Istree(root->left,cur,arr))//去左子树找找到返回truereturn true;if(Istree(root->right,cur,arr))//去右子树找找到返回truereturn true;arr.pop();//左右都没找到直接pop然后返回falsereturn false;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root==nullptr)return nullptr;if(root==p||root==q)return root;stack<TreeNode*> arr1,arr2;//创建stack栈Istree(root,p,arr1);//保留p和q的路径Istree(root,q,arr2);while(arr1.size()!=arr2.size())//让长的那个往上走和短的长度一致{if(arr1.size()>arr2.size()){arr1.pop();}if(arr2.size()>arr1.size()){arr2.pop();}}while(arr1.top()!=arr2.top())//找到第一个公共祖先{arr1.pop();arr2.pop();}return arr1.top();}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/468944.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

原子变量和原子操作

一、什么是原子操作 通常某一个变量的操作对应的CPU指令是大于一个的&#xff0c;在多线程环境下&#xff0c;为了确保对共享变量的操作在执行时不会被干扰&#xff0c;从而避免竞态条件和死锁等问题&#xff0c;使用原子变量。 原子变量可以看作是一种特殊的类型&#xff0c…

C++ 动态规划 计数类DP 整数划分

一个正整数 n 可以表示成若干个正整数之和&#xff0c;形如&#xff1a;nn1n2…nk &#xff0c;其中 n1≥n2≥…≥nk,k≥1 。 我们将这样的一种表示称为正整数 n 的一种划分。 现在给定一个正整数 n &#xff0c;请你求出 n 共有多少种不同的划分方法。 输入格式 共一行&…

Linux入门(1)Linux介绍

目录 1. 认识 Linux, 了解 Linux 的相关背景 1.发展史 2. 学会如何使用云服务器 3. 掌握使用远程终端工具 xshell 登陆 Linux 服务器 1. 认识 Linux, 了解 Linux 的相关背景 1.发展史 学习Linux系统编程&#xff0c;你可能要问Linux从哪里来&#xff1f;它是怎么发展的&am…

小游戏和GUI编程(7) | SimpleNN 界面源码解析

小游戏和GUI编程(7) | SimpleNN 界面源码解析 0. 简介 SimpleNN 是 AdamYuan 在高中一年级时用 1 天时间写出来的简易 CNN, 使用 SFML 做 UI, 用于交互式输入手写数字&#xff0c;这个数字被训练好的 CNN 网络执行推理得到识别结果, 它的运行效果如下&#xff1a; 这一篇我们…

【项目】高并发内存池

高并发内存池 【项目】高并发内存池项目介绍这个项目做的是什么&#xff1f; 内存池相关知识池化技术内存池malloc 定长内存池的实现高并发内存池整体框架设计ThreadCache对齐规则封装FreeList类封装thread cache类TLS无锁访问 CenctralCache整体设计页号规定span结构SpanList结…

2.8:Maefile、计算单词个数、判断文件类型、单词逆置

1.有main.c&#xff0c;test.c&#xff0c;test1.c&#xff0c;创建Makefile 程序代码&#xff1a; Makefile: 1 CCgcc2 EXEhello3 OBJS$(patsubst %.c,%.o,$(wildcard *.c))4 CFLAGS-c -o5 all:$(EXE)6 7 #hello依赖test.o main.o8 $(EXE):$(OBJS)9 $(CC) $^ -o $10 …

浅析Linux追踪技术之ftrace:Tracepoint

文章目录 概述Tracepoint使用定义Tracepoint添加Tracepoint调用 Tracepoint数据结构TRACE_EVENT实现DECLARE_TRACE__DECLARE_TRACE trace_xxx函数相关参考 概述 Tracepoint&#xff08;跟踪点&#xff09;是添加到代码流程中的调用点&#xff0c;并且允许开发者注册自定义的回…

TCP高频知识点

本篇文章主要讲述一下在面试过程中TCP的高频知识点 1.TCP三次握手流程图: 客户端发送一个SYN&#xff08;同步&#xff09;报文段给服务器&#xff0c;选择一个初始序列号&#xff0c;并设置SYN标志位为1。服务器接收到客户端的SYN报文段后&#xff0c;回复一个ACK&#xff08…

webgis后端安卓系统部署攻略,超详细Termux攻略

目录 前言 一、将后端项目编译ARM64 二、安卓手机安装termux 1.更换为国内源 2.安装ssh远程访问 3.安装文件远程访问 三、安装postgis数据库 1.安装数据库 2.数据库配置 3.数据导入 四、后端项目部署 五、自启动设置 总结 前言 因为之前一直做的H5APP开发&#xf…

如何利用SpringSecurity进行认证与授权

一、SpringSecurity简介 Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多&#x…

【排序】归并排序

归并排序 动图演示&#xff1a; 基本思想&#xff1a;分治思想 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子…

深入理解C语言(4):文件操作详解

文章主题&#xff1a;文件操作详解&#x1f30f;所属专栏&#xff1a;深入理解C语言&#x1f4d4;作者简介&#xff1a;更新有关深入理解C语言知识的博主一枚&#xff0c;记录分享自己对C语言的深入解读。&#x1f606;个人主页&#xff1a;[₽]的个人主页&#x1f3c4;&#x…