二叉树最近公共祖先问题(O(n) time 且只遍历一遍,O(1) Space (不考虑函数调用栈的空间))

来源:互联网 发布:淘宝粉丝怎么增加 编辑:程序博客网 时间:2024/06/05 09:11

问题:

找出二叉树中两个节点的最近公共祖先。

首先可以先参考下这个博客http://blog.csdn.net/cxllyg/article/details/7635992 ,写的比较详细,包括了节点包含父指针和不包括父指针的情况,还介绍了经典的Tarjan算法。

Tarjan算法很精妙,但是使用了并查集,需要额外O(n)的存储空间。上面博客中给的第三个方法也是需要记录根到节点的路径,需要O(log n)空间,当然考虑到一般情况下我们遍历树都是递归的方式,所以本身方法调用栈就是O(log n)空间占用率。 但是这是对于平衡的二叉树而言的,在最差情况下空间占用率还是O(n)。

所以,这里我给的算法不需要记录根到节点的路径,而且仅仅遍历树一遍就可以完成。

1. 首先深度遍历树,找到第一个节点,假设为p,这时设置两个节点的最近公共祖先为p

2. 继续深度遍历,找另外一个节点q, 假设这时找到q, 那么二者最近祖先就是p.

3. 否则,回退到上一层,这时二者的最近公共祖先也相应改成了p的父节点,因为以p为根的子树中没有发现另外一个节点q

4. 依此类推,找不到则继续回退到上一层,当找到q时,对应的二者最近公共祖先也就找到了。

5. 若是p==q,直接返回p作为最近公共祖先

6. 若二者不都存在于树中,则返回空。


public class CommonAncestor {public static void main(String[] args) {CommonAncestor ca=new CommonAncestor();TreeNode root=new TreeNode(0);TreeNode l1=new TreeNode(-1);TreeNode r1=new TreeNode(1);root.left=l1;root.right=r1;TreeNode l1l1=new TreeNode(-2);TreeNode l1r1=new TreeNode(-3);l1.left=l1l1;l1.right=l1r1;TreeNode r=ca.commonAncestor(root, l1, r1);System.out.println(r.val);}private TreeNode ancestor=null;private TreeNode firstFound=null;private boolean found=false;public CommonAncestor(){}public TreeNode commonAncestor(TreeNode root,TreeNode p,TreeNode q){this.ancestor=null;this.found=false;findCommonAncestor(root,p,q);if(found)return ancestor;elsereturn null;}private void findCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root==null)return ;if(found)return;this.findCommonAncestor(root.left, p, q);test(root,p,q);this.findCommonAncestor(root.right, p, q);test(root,p,q);}private void test(TreeNode root, TreeNode p, TreeNode q) {if(found)return;if(this.ancestor==null){if(root==p){this.ancestor=p;firstFound=p;if(p==q)found=true;}else if(root==q){this.ancestor=q;firstFound=q;if(p==q)found=true;}}else{if(root.left==this.ancestor||root.right==this.ancestor){this.ancestor=root;}if((root==p||root==q)&&root!=firstFound){found=true;}}}}





1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 开车久了肩膀疼怎么办 3岁宝宝撕书怎么办 孩子上幼儿园不爱写字怎么办 一年级小孩不爱做作业怎么办 小孩不愿多做作业怎么办 小孩一年级不自觉做作业怎么办 小孩会读不会写怎么办 好多字都不会写怎么办 写作业怎么办才能写快 五周宝宝爱玩不写字怎么办 爱玩手机的小孩怎么办? 一年级学生记不住生字怎么办 一年级小孩记不住生字怎么办 配镜度数高了怎么办 宝宝两岁半不肯坐马桶拉臭臭怎么办 儿子字写得不好 怎么办 小孩不听话不爱读书和写字怎么办 两岁宝宝不愿意穿衣服怎么办 做题粗心不认真怎么办 5岁宝宝不会写字怎么办 四岁宝宝不会写字怎么办 4岁宝宝不写字怎么办 四岁宝宝不写字怎么办 孩子学习粗心计算能力差怎么办 一年级的小朋友不爱看书怎么办 马上要生了害怕怎么办 孩子做题不爱读题怎么办 孩子作业写的慢怎么办 孩子学习不好怎么办我们有绝招 英语不会做题怎么办呢? 小学二年级孩子厌学怎么办 狗狗拉肚子不吃东西怎么办 小孩做作业时容易发呆怎么办 一上高速就犯困怎么办 孩子初中数学学不好怎么办 高三注意力不集中怎么办 考砸了家长打我怎么办? 高三学生困疲劳怎么办 高三晚上很困怎么办 孩子上高三压力大不想上学怎么办 高三的孩子压力大怎么办