求二叉树:二叉树最近公共祖先(LCA)问题 和 /节点最大距离问题.

一.最近公共祖先(LCA)

假设我们有指向所求两点的指针A和B

1.二叉树有指向父亲节点的指针

struct node
{
    ...
    struct node l,r,prv;  //left child,right child,father
}

如果我们有每个节点的深度信息的话: 

假设deep(A) > deep(B)  ,且deep(A)-deep(B) = s;

则让A向树根方向移动s距离.则A和B位于同一深度.

然后A和B同时向上移动,直到两点相遇.  第一次相遇的点就是父亲节点.

时间复杂度O(h)  ,h为树的高度

如果没有深度信息呢?

没有深度信息,我们可以先求两个点的深度信息啊,然后再使用上述的方法做.

如果强行不用深度信息呢?

既然没有深度信息,就无法做到恰好相遇.

我的思路是:

使用两个栈sA和sB记录下从A,B两点到达树根的路径(在树上一定是唯一的),然后sA和sB 的栈顶一定是树根root(这不是废话么).

不光栈顶相同,A和B的所有祖先都会相同.然后我们取sA 和sB最上面相同的序列就找到了所有公共祖先(自然就找到了最近公共祖先).

时间复杂度为O(h),空间复杂度为O(h).

2.二叉树没有父亲节点指针

struct node
{
    ...
    struct node l,r;  //left child,right child
}

那就只好DFS喽.

假设A节点的值为A,B节点的值为B,对于任何一个节点,如果所在子树包含A或B中的一个,则等于A或B,如果同时包含A和B,则它就是A和B的公共祖先.如果既不包含A也不包含B,那就没有搜索它的意义了.

然后用DFS求一下所有节点的值(实际用的时候不必要把所有值都求出来),递归(或者栈模拟)的时候出现的第一个公共祖先就是所求的最近公共祖先.

时间复杂度O(n) ,其中n为树所有节点个数.

3.如果树是特殊的树,比如二叉搜索树

既然有别的特点,那自然可以根据特点来优化喽.

对于二叉搜索树(假设没有deep和指向父亲的指针)来讲:

可以从根节点(root)开始搜索,如果A和B 的值在当前节点的值的同侧(A,B>root  或 A,B<root),就可以向一边搜索.如果A和B在当前节点的异侧(A< root < B 或 B<root <A ,这里的root 指的是当前子树的根,也就是当前节点),则当前节点就是最近公共祖先.

时间复杂度为O(h)

二.节点最大距离

给出一个二叉树,请你找到两个节点A和B,使两者距离最大.

显然,A和B一定为叶子.

O(n)的复杂度搜索吧.

每个节点维护四个信息:

左子树的深度,右子树的深度,左子树上的节点最大距离,右子树上的节点最大距离.

怎么样,从后两个信息可以看出递归的思路吧.(递归当然可以用栈模拟,就是代码麻烦一点,但是效率高).

然后对于root来讲,节点最大距离=max( 左子树上的节点最大距离, 右子树上的节点最大距离, 左子树深度+右子树深度+2)

解毕.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值