您当前的位置:首页 > 互联网教程

如何求二叉树最接近的共同祖先

发布时间:2025-05-22 14:33:54    发布人:远客网络

如何求二叉树最接近的共同祖先

一、如何求二叉树最接近的共同祖先

首先,题目中没有明确说明节点的结构,所以这里分这两种情况讨论:

在节点具有父指针的情况下,显然此二叉树就可以看成是通过父指针连接的"T"型链表,题目也就转化成查找"T"型链表的第一个公共节点。假设p,q分别为所求的两个节点,则通过遍历一遍可以知道p,q分别到根节点的长度pLen和qLen。这样就知道pLen和qLen之间长度之差,也就知道p、q到它们的第一个公共祖先节点k长度之差L。因为p,q到根节点的路径中都包含k到根节点的路径,所以pLen和qLen之差等于p、q到k的长度之差。然后,让p、q到根节点路径长度大的先向前走L,然后长度小再和大的同时向前遍历,当它们两指向同一个节点时,则那个节点即是所求。

*有父指针情况下,查找两个节点的最低公共节点

private BTNode<T> root;

public BTree(BTNode<T> r){

*查找两个节点的最低公共祖先节点

*@return BTNode<T>最低公共祖先节点,没有找到返回null

public BTNode<T> findLowestAncestor(BTNode<T> p,BTNode<T> q){

throw new NullPointerException();

int pLen=0,qLen=0;//p,q两个节点到根节点的路径长度

for(BTNode<T> ancestor=p.parent;ancestor!=null;ancestor=ancestor.parent)

for(BTNode<T> ancestor=q.parent;ancestor!=null;ancestor=ancestor.parent)

//如果p到根节点的长度比q长,则让p前进pLen-qLen

//如果q到根节点的长度比p长,则让q前进qLen-pLen

//此时,p和q到根节点的长度相同。假设k是最近的公共节点,则p和q到k的长度相同

//p和q按照相同步长1向前遍历,如果存在公共节点则p和去会同时指向它

while(q!=null&&p!=null&&p!=q){

*测试方法,在t中查找a,b的最低公共祖先节点

private static<T> void test(BTree<T> t, BTNode<T> a, BTNode<T> b){

BTree.BTNode<T> p=t.findLowestAncestor(b,a);

System.out.println(a.data+","+b.data+"的最低公共祖先节点是:"+p.data);

System.out.println(a.data+","+b.data+"没有公共祖先节点");

public static void main(String[] arg){

BTree.BTNode<String> g=new BTree.BTNode().data("g");

BTree.BTNode<String> f=new BTree.BTNode().data("f");

BTree.BTNode<String> e=new BTree.BTNode().data("e");

BTree.BTNode<String> d=new BTree.BTNode().data("d");

BTree.BTNode<String> c=new BTree.BTNode().data("c").left(f).right(g);

BTree.BTNode<String> b=new BTree.BTNode().data("b").left(d).right(e);

BTree.BTNode<String> a=new BTree.BTNode().data("a").left(b).right(c);

BTree<String> t=new BTree<String>(a);

public BTNode(BTNode<T> l,BTNode<T> r,BTNode<T> p,T d){

BTNode<T> left(BTNode<T> l){

BTNode<T> right(BTNode<T> r){

BTNode<T> parent(BTNode<T> p){

这种情况下,必须通过遍历查找一个节点的祖先集合,然后比较两个节点的祖先集合就可以找到最低的那个。这里采用后序遍历,并传入一个栈记录该节点的祖先节点。在每次访问一个节点时,先把这个节点压入栈,然后判断该节点是不是要查找的那个节点,如果是返回。接着查找它的左子树和右子树,当要查找的节点在它的左右子树中则返回。然后判断该节点与栈顶节点是否相同,是则弹出栈顶元素。这是因为相同就代表了在访问它的左右子树时没有添加新的节点,也就是说要查找的那个节点不在它的左右子树中,则该节点也就是不是要查找的节点的祖先。

*没有父指针情况下,查找两个节点的最低公共节点

private BTNode<T> root;

public BTree(BTNode<T> r){

*查找两个节点的最低公共祖先节点

*@return BTNode<T>最低公共祖先节点,没有找到返回null

public BTNode<T> findLowestAncestor(BTNode<T> p,BTNode<T> q){

throw new NullPointerException();

ArrayList<BTNode<T>> sp=new ArrayList<BTNode<T>>();

ArrayList<BTNode<T>> sq=new ArrayList<BTNode<T>>();

//祖先栈中,以先后顺序存储,所以这里倒序来遍历以便找到最低的那个祖先节点

for(int i=sp.size()-1;i>=0;i--)

for(int j=sq.size()-1;j>=0;j--)

*后序遍历二叉树,进行节点的搜索,当搜索成功时,将该节点的所有祖先存入栈中

*@param stack存储祖先节点的栈,这里使用ArrayList,因为后续查找最低公共祖先时需要遍历所有元素

*@return boolean是否搜索到该节点

private boolean travalPostOrder(BTNode<T> n,BTNode<T> p,ArrayList<BTNode<T>> stack){

if(travalPostOrder(n.left,p,stack))

if(travalPostOrder(n.right,p,stack))

int lastIndex=stack.size()-1;

//如果搜索完n的左右子树后,栈顶还是n,则代表n不是p的祖先节点,所以将n从栈中删除

*测试方法,在t中查找a,b的最低公共祖先节点

private static<T> void test(BTree<T> t, BTNode<T> a, BTNode<T> b){

BTree.BTNode<T> p=t.findLowestAncestor(b,a);

System.out.println(a.data+","+b.data+"的最低公共祖先节点是:"+p.data);

System.out.println(a.data+","+b.data+"没有公共祖先节点");

public static void main(String[] arg){

BTree.BTNode<String> g=new BTree.BTNode().data("g");

BTree.BTNode<String> f=new BTree.BTNode().data("f");

BTree.BTNode<String> e=new BTree.BTNode().data("e");

BTree.BTNode<String> d=new BTree.BTNode().data("d");

BTree.BTNode<String> c=new BTree.BTNode().data("c").left(f).right(g);

BTree.BTNode<String> b=new BTree.BTNode().data("b").left(d).right(e);

BTree.BTNode<String> a=new BTree.BTNode().data("a").left(b).right(c);

BTree<String> t=new BTree<String>(a);

public BTNode(BTNode<T> l,BTNode<T> r,T d){

BTNode<T> left(BTNode<T> l){

BTNode<T> right(BTNode<T> r){

在没有父指针时,还可以给每个节点添加一个计数器,在进入一个节点时加1,在退出该节点时减1。访问该节点时,如果要查找的节点在该节点的子树中,则返回。实际上,这和上面的算法思想是一样的,只是实现不同。

这两种算法的时间复杂度都是O(n),效率不错。没有父指针的情况,空间复杂度也是O(n)。

二、怎么判断自己适合学java啊

学习 Java,说白了,就是学习它的语法、功能、结构等。然后按照它的语法编写代码。新手刚接触可能会遇到很多问题,但没关系,这很正常。多看多问,多实践。

再来下判断自己适不适合学Java,首先,在心里问下自己这三个问题,如下:

如果对它不感兴趣,对于零基础的人来说,可能有些难懂。学着学着就开始有了厌学心理,根本学不进去!

网上有很多的学习视频,题主应该先去接触一下,自学一段时间,看看自己是否愿意往下学习,如果产生高额的兴趣,自制力和学习力足够的话,先把基础学扎实,再去考虑是否报班进行系统化的培训。

如果前两个问题都可以接受,那就是问下自己能否坚持的学下去,如果坚持不下去,那前面的都是白费。哪怕去培训完,但是一两年以后呢?人就是要持之以恒的学习进步,不然很快就会被社会给淘汰,更何况是在更新速度超快的数据时代。

如果以上三个问题都没有问题,个人认为是适合学习Java的。毕竟学一门技术本身就没有适不适合。

以上就是我对这个问题的看法,下面推荐下适合零基础学习的视频资料,可以看看自己是否有兴趣!

视频学习资料:

最后,扣字不易,还望看完点个赞!!!



相关内容FAQs: