leetcode 236. 二叉树的最近公共祖先 思考分析

目录

    • 题目
    • 思考分析
    • 改进

本文章代码思路来源于公众号【代码随想录】

题目

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

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x
的深度尽可能大(一个节点也可以是它自己的祖先)。”
在这里插入图片描述
在这里插入图片描述

思考分析

1、自下而上遍历对于此题有极大帮助,而后序遍历的特征便是优先处理叶子结点
2、如何判断一个节点是结点q和结点p的公共祖先:
如果找到一个结点,左子树出现结点p,右子树出现结点q,或者左子树出现结点q,右子树出现结点p。
确定返回值和参数
如果单纯只是告诉我们是否找到结点q或者p,那么返回值为bool就行了。
但是我们还要返回最近公共结点,所以返回值为TreeNode* 类型,如果遇到p或者q,就把p或者q返回,返回值不为空就说明了找到了q或者p。

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)

确定终止条件
如果找到结点p或者结点q或者结点为空,返回

if(root == q || root == p || root == NULL) return root;

确定单层逻辑
首先确定一点我们需要遍历树的所有结点。
直观上讲,如果找到了最近公共祖先,直接一路返回就可以了。如下图
在这里插入图片描述

但是事实上还要遍历根结点的右子树(即使现在已经找到了目标结点),这是因为在后序遍历中,如果想要利用left和right做逻辑处理,不能立即返回,而是要等到left和right的逻辑处理完之后才能返回。

left = 递归函数(root->left);
right = 递归函数(root->right);
left 和 right 的逻辑处理

所以我们要遍历整棵树。

TreeNode* left = lowestCommonAncestor(root->left,p,q);
TreeNode* right= lowestCommonAncestor(root->right,p,q);

1、如果left和right都不为空,说明此时root就是最近公共祖先。
2、如果left为空,right不为空,就返回right,说明目标结点是通过right返回的,反之依然。
在这里插入图片描述
3、如果left和right都为空,则返回left或者right都是可以的,也就是返回空。

if(left == NULL && right != NULL) return right;
else if(left != NULL && right ==NULL) return left;
else return NULL;		//此时只有left和right同时为空

整个遍历思路:
在这里插入图片描述

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*///如果一个结点不是另外一个结点的祖先,那么他们的最近祖先的深度一定是深度最小结点的深度-1//如果一个结点是另外一个结点的祖先,那么最近祖先就是是祖先的那个结点。
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL;		//此时只有left和right同时为空}
};

改进

在遍历完左子树之后,若是返回的left不是NULL,也不是p和q,则说明在左子树中已经找到了公共祖先了,此时可以直接返回left的值,无需再遍历右子树。这就是剪枝操作。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*///如果一个结点不是另外一个结点的祖先,那么他们的最近祖先的深度一定是深度最小结点的深度-1//如果一个结点是另外一个结点的祖先,那么最近祖先就是是祖先的那个结点。
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);//*****************剪枝操作******************if(left !=NULL && left !=p && left != q) return left; //*******************************************TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL;		//此时只有left和right同时为空}
};

加入打印信息,对遍历的过程更加了解熟悉;

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == NULL) cout<<"NULL"<<endl;else cout<<root->val<<endl;if(root == q || root == p || root == NULL ) return root;TreeNode* left = lowestCommonAncestor(root->left,p,q);//*****************剪枝操作******************if(left !=NULL && left !=p && left != q) return left; //*******************************************TreeNode* right = lowestCommonAncestor(root->right,p,q);if(left != NULL && right != NULL) return root;else if(left == NULL && right != NULL) return right;else if(left != NULL && right ==NULL) return left;else return NULL;		//此时只有left和right同时为空}
};

这一题感觉之后还需要多看几遍,多体会体会,感觉有些地方还是没理解。
若是有新的理解,再更新。

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

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

相关文章

leetcode 235. 二叉搜索树的最近公共祖先 思考分析

目录题目思考迭代法题目 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff0…

四、逻辑回归

逻辑回归logistic_regression(LR)其实是分类算法&#xff0c;而不是回归算法。 回归算法得到的是一个数&#xff0c;分类算法得到的是几个不同的类别。 逻辑回归就是通过函数将值转换为0-1之间&#xff0c;形成概率问题&#xff0c;从而实现了不同类别的分类。 Sigmoid 函数 …

运算符优先级

转载于:https://www.cnblogs.com/c-cloud/p/3280911.html

五、逻辑回归实验分析

所有代码块都是在Jupyter Notebook下进行调试运行&#xff0c;前后之间都相互关联。 文中所有代码块所涉及到的函数里面的详细参数均可通过scikit-learn官网API文档进行查阅&#xff0c;这里我只写下每行代码所实现的功能&#xff0c;参数的调整读者可以多进行试验调试。多动手…

二叉搜索树的插入、删除、修剪、构造操作(leetcode701、450、669、108)

目录1、leetcode 701. 二叉搜索树中的插入操作1、题目2、递归法3、迭代法2、leetcode 450. 二叉搜索树中的插入操作1、题目2、思路递归法3、迭代法4、删除结点的两个方法以及注意点3、leetcode 669. 修剪二叉搜索树1、题目2、思考与递归3、迭代法4、leetcode 108. 将有序数组转…

模拟退火算法解决np_P和NP问题与解决方案| 演算法

模拟退火算法解决npP问题 (P Problems) P is the set of all the decision problems solvable by deterministic algorithms in polynomial time. P是多项式时间内确定性算法可解决的所有决策问题的集合。 NP问题 (NP Problems) NP is the set of all the decision problems t…

POJ2251Dungeon Master

http://poj.org/problem?id2251 题意 &#xff1a; 就是迷宫升级版&#xff0c;从以前的一个矩阵也就是一层&#xff0c;变为现在的L层&#xff0c;" . "是可以走&#xff0c;但是“#”不可以走&#xff0c;从S走到E&#xff0c;求最短的路径&#xff0c;若是找不到…

六、聚类算法

一、聚类概念 1&#xff0c;通俗易懂而言&#xff0c;聚类主要运用于无监督学习中&#xff0c;也就是将没有标签的东西如何分为几堆儿。 2&#xff0c;无监督学习即没有标签&#xff0c;不知道这些玩意到底是啥。当然&#xff0c;有监督学习就是由标签&#xff0c;我们是提前知…

【C++grammar】string类和array类

目录1、C11的string类1、创建 string 对象2、追加字符串append函数3、为字符串赋值assign函数4、at, clear, erase, and empty函数5、比较字符串compare()6、获取子串at() 、substr()函数7、搜索字符串find()8、插入和替换字符串insert() 、replace()9、字符串运算符10、string…

六、聚类算法实战

所有代码块都是在Jupyter Notebook下进行调试运行&#xff0c;前后之间都相互关联。 文中所有代码块所涉及到的函数里面的详细参数均可通过scikit-learn官网API文档进行查阅&#xff0c;这里我只写下每行代码所实现的功能&#xff0c;参数的调整读者可以多进行试验调试。多动手…

超图软件试用许可操作步骤_软件中的操作步骤

超图软件试用许可操作步骤The software comprises of three things: Program code, Documentation, and the Operating Procedures. The Program code is the entire software code. The Documentation is produced while the development of the software itself for the time…

【嵌入式系统】STM32配置FreeRTOS以及利用多线程完成流水灯、按键、蜂鸣器、数码管工作

目录1、利用STM32CubeMX配置FreeRTOS2、完成流水灯、按键、蜂鸣器数码管工作1、在gpio.c和.h文件里面书写并声明按键扫描和led、数码管子程序2、在freertos.c文件里面设置全局变量并且在各自任务中载入程序3、关于FreeRTOS的注意事项1、利用STM32CubeMX配置FreeRTOS 假设我们之…

css模糊_如何使用CSS模糊图像?

css模糊Introduction: 介绍&#xff1a; Sometimes even the professional developers tend to forget the various basic properties which can be applied to solve very simple problems, therefore the fundamentals of developing a website or web page should be very …

七、决策树算法和集成算法

一、决策树算法 Ⅰ&#xff0c;树模型 决策树&#xff1a;从根节点开始一步步走到叶子节点&#xff08;决策&#xff09; 所有的数据最终都会落到叶子节点&#xff0c;既可以做分类也可以做回归 对于分类&#xff1a;是由众数决定的&#xff0c;例如爷爷奶奶妈妈都是负数&…

leetcode 538. 把二叉搜索树转换为累加树 思考分析

题目 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下&#xff0c;二叉搜索树满足下列约束条件&…

SQL中GROUP BY语句与HAVING语句的使用

最近在学习SQL Server相关知识&#xff0c;一直不知道怎么使用GROUP BY语句&#xff0c;经过研究和练习&#xff0c;终于明白如何使用了&#xff0c;在此记录一下同时添加了一个自己举的小例子&#xff0c;通过写这篇文章来加深下自己学习的效果&#xff0c;还能和大家分享下&a…

八、决策树算法实验可视化展示

一、树模型的可视化展示 官网下载安装包 右击管理员身份运行&#xff0c;直接下一步即可。 配置环境变量&#xff1a; 将安装好的可视化软件的bin文件夹路径添加到系统环境变量Path下即可 打开cmd&#xff0c;输入dot -version&#xff0c;出现相关信息即安装成功 二、决策…

机器学习笔记:PCA的简单理解以及应用建议

用notability做的笔记&#xff0c;比较随意&#xff0c;对于第五点的PCA错误使用需要特别强调。 目录1、PCA与线性回归2、PCA主成分数量选择3、压缩重现4、PCA应用建议5、PCA的错误使用1、PCA与线性回归 2、PCA主成分数量选择 3、压缩重现 4、PCA应用建议 5、PCA的错误使用

一、信用卡卡号识别

一、思路分析 大体思路&#xff1a;首先拿到一张银行卡&#xff0c;我们得有银行卡号数字的0-9样式的模板&#xff0c;然后再通过不同数字的轮廓的外接矩形来进行匹配&#xff0c;最终识别出银行卡号所对应的数字。 银行卡数字模板&#xff1a; 银行卡信息&#xff1a; 拿到…

bootstrap网格系统_如何使用Bootstrap网格系统?

bootstrap网格系统In the last article, we learned how to create a simple page of Bootstrap? Now, we will learn what is "Grid System" in Bootstrap and how we can use or implement it in our bootstrap page? As you know bootstrap is a mobile-friendl…