Solution1:我的答案

【针对阉割版的题目的偷鸡摸狗的做法】注意:书中的原题要更复杂一些,在牛客网中二叉树被设置为满二叉树且结点值从1开始,依次加1。

class LCA {
public:int getLCA(int a, int b) { //看来是一个数学推理题。。。// write code hereif (a == b)return a;int A = a, B = b;while (A != B) {if (A > B)A /= 2;else if (A < B)B /= 2;}return A;}
};

Solution2:正经做法

问题:找出二叉树中某两个结点的第一个公共祖先。
参考网址:
[1]https://blog.csdn.net/qinzhenhua100/article/details/64528136
[2]https://blog.csdn.net/xyzbaihaiping/article/details/52122885
题目分析:

假设1:这个二叉树是二叉排序树(O(N))

如果题目中的二叉树是二叉排序树,那么这道题目变的相对简单很多,我们只需要从根节点开始遍历,有以下三种情况发生:
(1)如果题目给的两个节点的值都大于当前节点,那么继续遍历当前节点的右子树
(2)如果题目给的两个节点的值都小于当前节点,那么继续遍历当前节点的左子树
(3)如果当前节点大于其中一个节点而小于其中另外一个节点,那么则返回该节点,该节点便是两个节点的公共祖先节点。

假设2:这个二叉树是普通的二叉树,但是存在指向父节点的指针

由于每个节点存在指向父节点的指针,所以如果给定任意一个节点,便可以找到从该节点到根节点的路径,因此我们可以找到题目中给予的两个节点分别到根节点的路径,因此该题目便变成了求两个单向链表的第一个公共节点。
假设2延伸:求两个单向链表第一个公共节点有两种方法:
(1)第一种方法是:两个链表如果有 公共节点,那么从第一个公共节点开始往后的所有节点都相同,我们首先遍历两个链表,求出两个链表的长度。然后设定两个指针分别指向这两个单向链表的头结 点,首先让链表较长的指针先移动,直至移动的剩余长度与链表较短的那个链表长度相同为止,这个时候两个指针开始同时移动,直到两个指针指向的节点相同,这 个节点便是这两个单向链表的第一个公共节点。
(2)第二种方法是:可以设置两个栈,首先分别把两个链表中的节点依次入栈,接下来从两个栈中同时一个一个的将节点弹出,遇到第一对弹出的节点不同时,那么前一次弹出相同的节点便是这两个链表的第一个公共节点。

【重点】假设3:这个二叉树是普通的二叉树,并且不存在指向父节点的指针

<方法1>:判断子树中是否存在某节点(时间复杂度O(N2)O(N^2)O(N2))

首先建立一个方法判断一棵树中是否存在某个节点,这个比较简单,只需要遍历整棵树,如果存在返回true,如果不存在则返回false。
接下来的判断过程就相当于二叉排序数的判断过程了,只不过二叉排序树判断一个节点是否在左子树或者右子树中只需要和父节点比较,而普通的树需要遍历整个左子树或者右子树才能实现。
(1)如果题目给的两个节点都在右子树,那么继续遍历当前节点的右子树
(2)如果题目给的两个节点都在左子树,那么继续遍历当前节点的左子树
(3)如果给定的两个节点一个在左子树,一个在右子树,则返回当前节点。

<方法2>:寻找从根节点到子节点的路径

如果找到从根节点到两个子节点的路径,那么题目就迎刃而解了,可以用栈遍历二叉树,最后找到从根节点到相应节点的路径,类似二叉树的先序非递归遍历一样,先遍历根节点,接着遍历左子树,接着遍历右子树,直到遍历到相应节点为止,这时栈中的元素便是路径元素。

<方法3>:递归遍历

设根节点为root,两个节点分别为p,q,用前序遍历方法递归遍历整个二叉树,如果只找到p则返回p,如果只找到q则返回q,如果一个节点的左右子树分别找到p,q,则返回该节点,其他情况返回NULL。
方法1的代码如下:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class LCA {
public:TreeNode *commonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) {if (!covers(root, p) || !covers(root, q))return null;return commonAncestorHelper(root, p, q);}bool covers(TreeNode *root, TreeNode *p) {if (!root) return NULL;if (root == p) return true;return covers(root->left, p) || covers(root->right, q);}TreeNode *commonAncestorHelper(TreeNode *root, TreeNode *p, TreeNode *q) {if (!root) return NULL;if (root == p || root == q) return root;bool is_p_in_left = covers(root->left, p);bool is_q_in_right = covers(root->right, q);//若p和q不在同一边则返回rootif (is_p_in_left != is_q_in_right) return root;//否则p和q在同一边,递归访问那一边TreeNode *tmp = is_p_in_left? root->left : root->right;return commonAncestorHelper(tmp, p, q);}};

程序员面试金典——4.7最近公共祖先相关推荐

  1. 最近公共祖先 牛客网 程序员面试金典 C++ Python

    最近公共祖先 牛客网 程序员面试金典 C++ Python 题目描述 有一棵无穷大的满二叉树,其结点按根结点一层一层地从左往右依次编号,根结点编号为1.现在有两个结点a,b.请设计一个算法,求出a和b ...

  2. 程序员面试金典--第k个数

    程序员面试金典--第k个数 题目描述 有一些数的素因子只有3.5.7,请设计一个算法,找出其中的第k个数. 给定一个数int k,请返回第k个数.保证k小于等于100. 测试样例: 3 返回:7 逐个 ...

  3. 程序员面试金典 - 面试题 08.13. 堆箱子(DP)

    1. 题目 堆箱子.给你一堆n个箱子,箱子宽 wi.深 di.高 hi. 箱子不能翻转,将箱子堆起来时,下面箱子的宽度.高度和深度必须大于上面的箱子. 实现一种方法,搭出最高的一堆箱子.箱堆的高度为每 ...

  4. 程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)

    文章目录 1. 题目 2. 解题 2.1 超时解 2.2 二分查找 1. 题目 有个马戏团正在设计叠罗汉的表演节目,一个人要站在另一人的肩膀上.出于实际和美观的考虑,在上面的人要比下面的人矮一点且轻一 ...

  5. 《程序员面试金典》解题目录(更新完毕)

    题目来源于LeetCode上的<程序员面试金典>,这里做一个目录方便大家查找.另外有本人的LeetCode解题目录.<剑指Offer>解题目录.LintCode代码能力测试CA ...

  6. C#LeetCode刷题-程序员面试金典

    本文由 比特飞 原创发布,欢迎大家踊跃转载. 转载请注明本文地址:C#LeetCode刷题-程序员面试金典 | .Net中文网. C#LEETCODE刷题概述 概述 所有LeetCode程序员面试金典 ...

  7. 《程序员面试金典》+《算法导论》

    <程序员面试金典>+<算法导论> 因为最近可能会面临一波面试,但是自己各种算法以及常见的问题的熟悉程度感觉还不够,但是由前几次的代码优化经验来看,算法优化可以说是代码优化的重中 ...

  8. 程序员面试金典——18.13 最大字母矩阵

    程序员面试金典--18.13 最大字母矩阵 在牛客网上把此题的难度给大大降低了......... Solution1: 参考网址:https://www.nowcoder.com/questionTe ...

  9. 程序员面试金典——18.12最大和子矩阵

    程序员面试金典--18.12最大和子矩阵 Solution1: 参考网址: [1]https://www.cnblogs.com/GodA/p/5237061.html 思想讲的很清楚~ [2]htt ...

最新文章

  1. python框架flask系列(2),Python的Web框架之Flask(2)
  2. 认清JavaScript和JAVA全局变量和局部变量的作用域
  3. 16、分布式文档系统--document的_source元数据以及定制返回结果解析(来自学习资料+自己整理)
  4. 增加外键时候的一个小错误
  5. 201112阶段二qt图形视图框架
  6. Linux 下, npm i 老是被killed 已杀死
  7. golang 结构体判空
  8. Unity上的Oculus Quset2开发(2) —— 在VR里打棒球
  9. 三维点云学习(3)6- 实现K-Means
  10. 数字电平(一):TTL和CMOS
  11. Node.js之Stream可读流readable
  12. python 导入.so 文件
  13. dw中html颜色的设置颜色代码,利用Dreamweaver(DW)快速输入CSS颜色代码值
  14. 微型计算机指的是重量轻,微型计算机按什么分类
  15. 江南大学物联网工程学院数据库课程实验一作业1实验报告
  16. 凉宫春日的忧郁[数学题]
  17. Java 时间相关 获取某月的某一天
  18. 生物信息学(4)——多序列比对之CLUSTAL算法详解及C++实现
  19. 计算机科学主题 一亩三分地 每日答题 题库
  20. 项目经理如何写年终总结,范文+PPT模板

热门文章

  1. python35个关键字_Python必须了解的35个关键词
  2. pid算法matlab仿真程序和c程序,pid算法matlab仿真程序和c程序.doc
  3. php 获取音视频时长,PHP 利用getid3 获取音频文件时长等数据
  4. jdom解析xml文件_JDOM编辑XML文件示例
  5. linux 更改ssh端口_如何在Linux中更改SSH端口-简易指南
  6. python参数检查类型_Python类型检查
  7. kotlin null_Kotlin Null安全– Kotlin可空
  8. 苹果x翻新机序列号开头_Android翻新电话每隔X秒
  9. struts的输入验证服务器端与客户端
  10. ROS的学习(十五)验证publisher和subscriber