问题:求二叉树中两个结点p,q的最近公共祖先
思路:第一种方法是二叉树的递归,当搜索是当前结点为p或者为q时,直接返回对应结点。然后再左右子树的返回情况
1、如果左右子树非空,则当前结点就是要找的最近公共祖先
2、如果左子树返回的为空,右子树返回的不为空,则以右子树的结果返回
3、如果左子树返回的不为空,右子树返回的为空,则以左子树的结果返回。
第二种方式就是先求得p的父结点、父父结点等保存,然后在判断q的父结点、父父结点等是在在保存的结果中出现,就是该结点就是要求的结点。
第三种方式 就是使用tarjan的离线算法
第四种方法根据树的高度h将树分成 sqrt(h)段,第一段是从[0,sqrt(h)-1],第二段是[sqrt(h), 2 * sqrt(h) -1],...。使用变量p[i]来表示结点i在上一段中最后一层的祖先。结点编号从1开始,因此对于深度小于sqrt(h)的有p[i]=1,其它段的第一层结点的p[i]等于i的父结点,而非第一层的p[i]=p[parent[i]],在求u,v的最近公共祖先时,先找到u,v的所在的段
第五种方法是通过将LCA问题转为RMQ问题,通过遍历树得到欧拉序以及记录结点访问时第一次出现在欧拉序中的位置,通过u,v得到u,v首次出现在欧拉序中的位置,在这区间查找深度最小的即可
具体代码参考: