问题:

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

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

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

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

  1. LCA 学习算法 (最近的共同祖先)poj 1330

    Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20983   Accept ...

  2. 二叉树系列 - 求两节点的最低公共祖先,例 剑指Offer 50

    前言 本篇是对二叉树系列中求最低公共祖先类题目的讨论. 题目 对于给定二叉树,输入两个树节点,求它们的最低公共祖先. 思考:这其实并不单单是一道题目,解题的过程中,要先弄清楚这棵二叉树有没有一些特殊的 ...

  3. 最近公共祖先 LCA Tarjan算法

    来自:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html 对于一棵有根树,就会有父亲结点,祖先结点,当然最近公共祖先就是这两个 ...

  4. hdu 2586(最近公共祖先LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路:在求解最近公共祖先的问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好 ...

  5. 求职之C++小知识点整理

    1.顺序容器 1.顺序容器:vector,deque,list,forward_list,array,string.其中除list和forward_list外,其它都支持快速随机访问. deque a ...

  6. 岛屿的个数12 · Number of Islands12

    [抄题]: 给一个01矩阵,求不同的岛屿的个数. 0代表海,1代表岛,如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右为相邻. [ [1, 1, 0, 0, 0], [0, 1, 0, 0 ...

  7. 07. Go 语言接口

    Go 语言接口 接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程. Go 语言中使用组合实现对象特性的描述.对象的内部使用结构体内嵌组合对象应该具 ...

  8. LCA算法的理解

    LCA思想: 在求解最近公共祖先为问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好的处理技巧就是在回溯到结点u的时候,u的子树已经遍历,这时候才把u结点放入合并集合中, 这样u结 ...

  9. poj1330Nearest Common Ancestors 1470 Closest Common Ancestors(LCA算法)

    LCA思想:http://www.cnblogs.com/hujunzheng/p/3945885.html 在求解最近公共祖先为问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好 ...

随机推荐

  1. 特里-HDOJ-1671

    Phone List Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  2. EF 分离实体

    具体步骤: 新建测试项目:如图 其中Respository和Model层均为类库项目, 1.在Respository层添加ADO.NET实体数据模型, 2.复制Model.tt文件到Model层,这是 ...

  3. android uiautomator自己主动化測试

    前提是自己电脑上配置好JDK,android和ant的环境 1.命令行下进入\Android-sdk\tools\文件夹下,执行命令:    android list    查看相应android版本 ...

  4. Android-它们的定义Notification

    Android-它们的定义Notification 2014年4月26日  消息栏的消息,想必各位Android发烧友非常清楚知道是什么,比方我们下载了一个应用,它可能会定时推送些消息到我们的手机中. ...

  5. poj1236 有向图加边变成强连通图

    给我们一个有向图,有两个问题 1.最少要给多少个点发消息,才能使得所有的点都收到消息(消息可以随边传递) 2.最少需要多少条边才能使得图变成强连通图 对于一个强连通分量,可以当做一个点来考虑,所以我们 ...

  6. 黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级)

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(二) Cryptography Application Block (高级) 本章介绍的是企业库加密应用程序模块 ...

  7. uptime

    linux uptime命令主要用于获取主机运行时间和查询linux系统负载等信息.uptime命令过去只显示系统运行多久.现在,可以显示系统已经运行了多长时间,信息显示依次为:现在时间.系统已经运行 ...

  8. Python学习路径8——Python对象2

    1.标准型运营商 1.1对象值对照 比较运算符用于如果相同类型的对象是相等.所有的内建类型的是在比较操作中支持,返回布尔比较操作值True 或 False. <span style=" ...

  9. C该程序生成一个唯一的序列号

    在实际的软件开发项目,通常,它包括产生一唯一的序列号.在本文中,一个切实可行的方案,例如,它引入了一个唯一的序列号生成过程. 本文生成的序列号的样式为:MMDDHHMINSS_XXXXXX. 程序例如 ...

  10. 协同编辑多人word一个小技巧文件

    协同编辑多人word窍门 近期在工作中编写标书时因为不同内容分给了各个部门去制作.可是在汇总后遇到再次改动的问题.对方把改动后的部分文档发给我粘贴到标书中后,所有的格式所有都乱了.又一次整理格式.标题 ...