• 二元最近的共同祖先问题(O(n) time 而且,只有一次遍历,O(1) Space (它不考虑函数调用栈空间))


    问题:

    找到两个节点的二叉树的最近的共同祖先。

    首先可以参考这个博客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;
    		else
    			return 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;
    			}
    		}
    	}
    
    }
    





    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    段错误诊断!
    kissthank
    c实现面向对象编程(3)
    字符串转换成数字以及注意事项
    【Java并发编程实战】-----“J.U.C”:CLH队列锁
    c编程:僵尸吃大脑
    展示C代码覆盖率的gcovr工具简单介绍及相关命令使用演示样例
    最优化学习笔记(三)最速下降法
    maven学习
    ASP.NET MVC 入门4、Controller与Action
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4800766.html
Copyright © 2020-2023  润新知