`
384444165
  • 浏览: 255047 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

LCA离线算法Tarjan(2)案例1——求二叉树中节点的最大距离

阅读更多

不搞ACM,就举个笔试面试题库里的题目说一下Tarjan算法的应用吧。这是“结构之法 算法之道”上的100题里面第11题,题目如下:

 

求二叉树中节点的最大距离...
如果我们把二叉树看成一个图,
父子节点之间的连线看成是双向的,
我们姑且定义"距离"为两节点之间边的个数。
写一个程序,
求一棵二叉树中相距最远的两个节点之间的距离。

 

不多介绍了,这个将LCA的代码该很少的部分就可以直接应用。暂时没有想出来很好的可以通用的并查集、Tarjan算法接口,所以就先重复代码解决问题吧。

这个问题只需要引申一下就很清晰了:

 

问题为:找距离最近公共祖先的距离最长的两个点

LCA问题:计算每个节点的层次,计算两个节点到最近公共节点的层次和为距离

 

代码如下,有点长,带了个简单测试用例:

 

public class Questions11 {

	public static void main(String[] args){
		/*
		 *    0
		 *  1   2
		 * 3 4
		 */
		
		List<Node<Integer>> list = new ArrayList<Node<Integer>>();
		for(int i=0; i<5; i++){
			list.add(new Node<Integer>(i));
		}
		
		list.get(0).children.add(list.get(1));
		list.get(0).children.add(list.get(2));
		
		list.get(1).children.add(list.get(3));
		list.get(1).children.add(list.get(4));
		
		solve(list.get(0), list);
	}
	
	//找距离最近公共祖先的距离最长的两个点
	//计算每个节点的层次,计算两个节点到最近公共节点的层次和为距离
	public static void solve(Node<Integer> root, List<Node<Integer>> allNodes){
		LCA_Tarjan<Integer> lca = new LCA_Tarjan<Integer>();
		assertEquals(3, lca.getMaxDistance(root,allNodes));
	}
	
	public static class LCA_Tarjan<T> {
		
		public static class Node<T>{  
		    T data;         //Node的数据
		    int level = 0;
		    Node<T> father; //父节点/祖先节点
		    List<Node<T>> children;
		    
		    public Node(){}
		    
		    public Node(T data){  
		        this.data = data;  
		        this.father = this;
		        children = new ArrayList<Node<T>>();
		    }
		}  
		
		public static class Pair<T>{
			Node<T> p, q;
			Node<T> lca;
			public Pair(Node<T> p, Node<T> q){
				this.p = p;
				this.q = q;
			}
		}

		List<Node<T>> allNodes;
		Map<Node<T>,Boolean> checked;
		int maxLen = 0;
		
		public int getMaxDistance(Node<T> root, List<Node<T>> allNodes){
			this.allNodes = allNodes;
			checked = new HashMap<Node<T>,Boolean>();
			LCA(root,0);
			return maxLen;
		}
		
		private void LCA(Node<T> u, int level){
			for(Node<T> v:u.children){
				LCA(v, level++);
				union(u, v);
			}
			checked.put(u, true);
			u.level = level;
			for(Node<T> n:allNodes){
				if(n==u)
					continue;
				Boolean b = checked.get(n);
				if(b!=null && b){
					int fatherLevel = find(n).level;
					if(maxLen<(u.level+n.level-2*fatherLevel))
						maxLen = u.level+n.level-2*fatherLevel;
				}
			}
		}
		
		//--------------------------------------------------------------------
		//并查集
		    
		/**
		 * 找到祖先节点
		 * @param x
		 * @return
		 */
		public Node<T> find(Node<T> x){  
			//当自己是祖先的时候直接返回
			if (x == x.father){
				return x;
			}
			
			//当自己的父节点不是祖先的时候,压缩树直接连接到祖先节点
			x.father = find(x.father);
			
			return x.father;
		}  
		  
		/**
		 * x和y节点之间有连接,将其所属集合连接。rank值小的树加到rank值大的树下面。相同时y加到x下。
		 * @param x
		 * @param y
		 */
		public void union(Node<T> x, Node<T> y){ 
			Node<T> xFather = find(x);
			Node<T> yFather = find(y);
			//当两个结合不联通的时候根据rank值,将rank值小的树加到rank值大的树下面
			if(xFather==yFather){
				return;
			}else{
				yFather.father = xFather;
			}
		}  
	}
}

 

做完看到编程之美上有这个题目,还没仔细看解法,这里主要是说一下LCA怎么用在这个题,这样做下来还是挺简单的,而且时间复杂度LCA只有O(n+Q),还不错了

 

 

0
2
分享到:
评论

相关推荐

    LCA的tarjan算法

    对于LCA问题,有不少解法,这儿提供了tarjan算法,这是一种离线算法,读入所有输入然后一并处理,并且利用并查集的思想,从根节点开始DFS,对每一个DFS的节点,先把他的父亲节点指向本身,没访问完一个子节点,然后...

    Tarjan 的 LCA 算法

    c++写的Tarjan 的 LCA 算法,最近公共祖先算法,可供算法学习参考

    LCA.zip_lca Tarjan pascal_lca pascal_tarjan lca pascal

    Tarjan算法求最近公共祖先,输入树和询问,按询问顺序回答

    Tarjan应用LCA

    Tarjan应用LCA

    LCA (最近公共祖先) Tarjan & 倍增

    理解:离线算法,建好树后再查询,一次DFS 吧所有查询解决完。 时间复杂度:O(n+q); n个点 q次询问 补一下:链式向前星,并查集 ,Tarjan 代码 #include #include #include #include #include using namespace ...

    Tarjan算法

    最近公共祖先LCA Tarjan算法

    contest_tarjan_LCA_源码

    tarjan离线算法求最近公共祖先。对于有根树T的两个结点u、v,最近公共祖先LCA(T

    Pro 俩顶点之间的长度

    这道题结果输出所有问询距离总数,可采用了Tarjan离线算法(一次读入所有查询,统一处理),基于DFS和并查集(这两个知识点西安讲师在视频中讲过), (根节点可以任选)在该过程中,维护一个所有节点到选定根的距离...

    Tarjan算法讲义

    Tarjan 算法是图论中非常实用 / 常用的算法之一,能解决强连通分量,双连通分量,割点和桥,求最近公共祖先(LCA)等问题。 关于 Tarjan 算法,笔者将用一系列文章系统介绍 Tarjan 算法的原理以及其主要解决的问题...

    slca算法的实现

    一个很经典的论文,关于slca的论文,现在关于查询方面的知识,好多都是基于slca的

    论文研究-二叉树演绎于结点序号内蕴性质的快速算法.pdf

    通过研究二叉树结点顺序存储序号的性质,演绎出了二叉树非递归无堆栈的一些新算法,包括完全二叉树两结点最近共同祖先(LCA)的查询算法、中序遍历算法、顺序序列与中序序列的互转算法以及从中序序列恢复层次结构的...

    常用算法代码

    | RMQ 离线算法 O(N*LOGN)+O(1)求解 LCA 19 | LCA 离线算法 O(E)+O(1) 20 | 带权值的并查集 20 | 快速排序 20 | 2 台机器工作调度 20 | 比较高效的大数 20 | 普通的大数运算 21 | 最长公共递增子序列 O(N^2) ...

    Pascal LCA 倍增法详解及代码

    LCA 详解以及完整代码详细介绍了倍增法的原理以及Pascal的完整代码 很好很强大

    Tarjan算法 讲解

    Tarjan算法的图文讲解,非常详细易懂。 强连通分量算法

    lca_one_layer.zip_LCA_LCA算法_图像分析_图像基元_基元 matlab

    LCA (Lobe Component Analysis) Lobe成分分析法,图像基元的特征检测算法。

    ACM 算法模板集

    2. 球面上两点最短距离 3. 三点求圆心坐标 4. 三角形几个重要的点 七. 专题讨论 1. 树状数组 2. 字典树 3. 后缀树 4. 线段树 5. 并查集 6. 二叉堆 7. 逆序数(归并排序) 8. 树状DP 9. 欧拉路 10. 八数码 11. 高斯消元...

    LCA多种算法讲解(含版题代码)

    LCA讲解,有图片与版题(含代码)帮助理解

    上海交通大学ACM算法模板

    2. 球面上两点最短距离 3. 三点求圆心坐标 4. 三角形几个重要的点 专题讨论 1. 树状数组 2. 字典树 3. 后缀树 4. 线段树 5. 并查集 6. 二叉堆 7. 逆序数(归并排序) 8. 树状DP 9. 欧拉路 10. 八数码 11. 高斯消元法 ...

    中文LCA Training 2

    LCA 中文教程,内部资料--产品结构管理,还不错啊,可以看下

    ACM图论模板合集.pdf

    图论--LCA--Tarjan(离线) 图论--LCA--树上倍增法(在线) 图论--LCA--在线RMQ ST 最小环: 图论--最小环--Floyd模板 树的直径: 图论--树的直径--DFS+树形DP模板 树的重心: 图论--树的...

Global site tag (gtag.js) - Google Analytics