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

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

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

问题:

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

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

}


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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/117080.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 韩国饮食,生活用品,娱乐,车费费用一览表

    韩国饮食,生活用品,娱乐,车费费用一览表

    2021年8月30日
    51
  • python贪吃蛇最简单代码_用python写贪吃蛇

    python贪吃蛇最简单代码_用python写贪吃蛇一、前言之前版本很多小伙伴都觉得难度过高,另外也有粉丝问还能不能精简代码。所以这版降低了难度(由原来过关增加5km/h改为3.5KM/h),并通过反射代替IFELSE的写法,并删除了一些冗余的代码,将代码压缩到了71行(不必要的压缩代码是不建议的,这里压缩代码只是为了好玩)二、实现效果三、环境要求python3+pygame包安装命令:打开cmd输入:pipinstallpygame四、源码分享importpygameimportsysimportra

    2025年8月28日
    11
  • 微信公众号平台开发测试怎么做_软件测试怎么测小程序

    微信公众号平台开发测试怎么做_软件测试怎么测小程序微信公众号与微信客户端之间的通信机制如下图所示:公众账号需要根据不同微信用户的不同消息做出不同的响应,所以每一个公众账号需要开发自己独有的系统,这套系统需要运行在公网环境下,但是我们通常普通开发人员没有这个条件,所以我选择了新浪云(天真的我以为是免费的,结果花了10个小洋)。第一步注册微信公众账号我用已有的微信号,扫码即可得到一个第二步注册新浪云

    2025年6月11日
    4
  • 安防监控行业未来发展解析「建议收藏」

    安防监控行业未来发展解析「建议收藏」随着我国社会经济的快速发展,“十二五”期间政府继续大力推动“平安城市”、“智慧城市”建设,另外安防监控设备企业自身的创新拓展加之与IT企业、电信企业、家电企业的交融发展,极大地扩充了安防的内涵和应用领域。我国安防行业又将进入一个十分重要的发展时期,机遇与挑战并存:市场规范有待加强,企业经营有待引导,未来发展走多元化、专一化之路。  安防监控市场规范有待加强  虽然安防…

    2022年6月28日
    66
  • foreach遍历list删除元素一定会报错?

    list集合平常自以为用的非常熟了,原来只是用add()方法熟练而已,碰到remove一报错就彻底暴露了自己的短板啦。来,给list集合删除某些元素,先上一段代码:   1)报错啦   Listlist=newArrayList();list.add(“1”);list.add(“2”);list.add(“3”)

    2022年4月6日
    96

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号