求一个树的最低公共祖先

来源:互联网 发布:mac隐藏照片 编辑:程序博客网 时间:2024/05/29 07:47

这个题也是剑指offer上面的题,所涵盖的知识点比较广。所以把它拿出来,跟大家分享下。

题目:

给定一颗树和树中的两个节点,如何快速找到这两个节点的最低公共祖先节点?

这么一个题根据条件不同有不同的解法:

条件一:这棵树是一棵二叉排序树

解法:由二叉排序树的性质可知,树中任何一个节点的值都大于左子树的任意节点的值,小于右子树中任意节点的值。由这一性质我们可以从根节点开始寻找公共祖先,

如果根节点的值大于等于两个节点的值,那么这两个节点的公共祖先在根节点的左子树上,使用一个循环可以实现;

如果根节点的值小于等于两个节点的值,那么这两个节点的公共祖先在根节点的右子树上,使用一个循环可以实现;

如果根节点的值介于两个节点值之间,那么这个根节点就是我们要找的公共祖先;




条件二:如果树不是一颗二叉排序树,甚至不是一颗二叉树。但是树中每个节点中有一个指向父节点的指针。

解法:由于每个节点中都有一个指向父节点的指针,如果只看从两个节点出发的父指针直到根节点,相当于是两个链表。那么这个问题可以转化为“求单链表的第一个公共节点”的问题。

关于求两个单链表的第一个公共节点的解法在上一篇博客中有详细介绍,这里只是说下大致解法,具体不在详细赘述。

解法一:暴力搜索,对一个链表中的每一个节点都扫描另外一个链表,检查是不是公共节点;

解法二:借助于两个栈。将两个链表中的节点依次放入各自的栈中,这样公共节点在栈的上面。不断出栈,到最后一个公共元素就是我们要找的“第一个公共节点”;

解法三:先扫描两个链表,然后从较长的先走.....


无任何条件,也就是说在一颗树(不一定是二叉树)上找两个节点的最低公共祖先。其中节点中没有父指针。

这样的话我有两个思路用来解决。

思路一:

对于树中的根节点,我们遍历以该节点为根节点的子树,检查其中是否包含那两个节点。

如果包含,则分别检查左子树、右子树。如果两个节点分布在左右子树上,那么当前点就是这两个点的最低公共祖先。

如果两个节点都在左子树上,那么在左子树上进行遍历,不用对右子树进行遍历了。

例子:


按照这个思路,首先判断以1为根节点的子树中是否包含6和90?答案:同时包含。

然后再判断以1的第一个孩子,2为根节点的子树中是否包含6和90?答案:同时包含。

然后在判断以2的第一个孩子,18为根节点的子树中是否包含6和90?答案:一个也不包含。

然后在判断以2的第二个孩子,11为根节点的子树中是否包含6和90?答案:一个也不包含。

然后在判断以2的第三个孩子,4为根节点的子树中是否包含6和90?答案:同时包含。

然后在判断以4的第一个孩子,6为根节点的子树中是否包含6和90?答案:只包含6。

然后在判断以4的第二个孩子,5为根节点的子树中是否包含6和90?答案:只包含90。

因此,我们可以得出节点4是6和90的最低公共祖先。

我们在判断某个子树中是否包含两个节点,可以使用某种遍历方式(先序,中序,后序)



思路二:

使用先序遍历从根节点开始,并使用一个vector来保存遍历过程中走过的路径。当遇到6或者90时,就将该路径生成一个链表。这样遍历完整棵树后就可以得到两个从根节点开始到两个节点的链表,其中前半部分的节点是俩那个链表的公共节点,最后一个公共节点就是最低公共祖先。


对应的两个链表分别为:

1->2->4->6;

1->2->4->5->90;

因此最低公共祖先为4.

阅读全文
0 0