求树中两个节点的最低公共父节点
来源:互联网 发布:数据开发工程师 编辑:程序博客网 时间:2024/06/18 04:25
这个题目其实是具有二义性的,因为没有对树的结构进行说明,例如二叉树搜索树,具有指向父节点引用的树,和普通的树,针对三种情况对应的处理方式是不同的,接下来我们结合三种情况来具体分析一下:
二叉搜索树
根据二叉搜索树的性质,根节点大于其左节点,小于其右节点,因此我们可以用这个条件来判断,找到最低的大于leftnode且小于rightnode的那个节点即是目标:
public class BinaryTreeNode { public int value; public BinaryTreeNode leftNode; public BinaryTreeNode rightNode; public BinaryTreeNode(int value) { //搜索二叉树是否平衡与元素的插入顺序是有关的 this.value = value; leftNode = null; rightNode = null; } public static BinaryTreeNode getLowestCommonAncestor(BinaryTreeNode rootParent, BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2) { if (root == null || node1 == null || node2 == null) { return null; } if ((root.value - node1.value) * (root.value - node2.value) < 0) { return root; } else if ((root.value - node1.value) * (root.value - node2.value) > 0) { BinaryTreeNode newRoot = ((root.value > node1.value) && (root.value > node2.value)) ? root.leftNode : root.rightNode; return getLowestCommonAncestor(root, newRoot, node1, node2); } else { return rootParent; } } public static void main(String[] args) { BinaryTreeNode A = new BinaryTreeNode(4); BinaryTreeNode B = new BinaryTreeNode(2); BinaryTreeNode C = new BinaryTreeNode(6); BinaryTreeNode D = new BinaryTreeNode(1); BinaryTreeNode E = new BinaryTreeNode(3); BinaryTreeNode F = new BinaryTreeNode(5); BinaryTreeNode G = new BinaryTreeNode(7); A.leftNode = B; A.rightNode = C; B.leftNode = D; B.rightNode = E; C.leftNode = F; C.rightNode = G; BinaryTreeNode res1 = getLowestCommonAncestor(null, A, E, F); BinaryTreeNode res2 = getLowestCommonAncestor(null, A, D, E); BinaryTreeNode res3 = getLowestCommonAncestor(null, A, B, D); System.out.println("The lowest common ancestor of 3 and 5 is " + res1.value); System.out.println("The lowest common ancestor of 1 and 3 is " + res2.value); System.out.println("The lowest common ancestor of 1 and 2 is " + res3.value); }}
使用的例子如图:
(注:后续两个例子的树的构造同理,故不再赘述)
具有指向父节点引用的树
可以将问题看做两个链表求最先公共结点的问题,因此需要先求出包含两个目标节点所构成的“链表”的长度:
public class NewBinaryTreeNode { public int value; public NewBinaryTreeNode parentNode; public NewBinaryTreeNode leftNode; public NewBinaryTreeNode rightNode; public NewBinaryTreeNode(int value) { this.value = value; parentNode = null; leftNode = null; rightNode = null; } public static NewBinaryTreeNode getLowestCommonAncestor1(NewBinaryTreeNode root, NewBinaryTreeNode node1, NewBinaryTreeNode node2) { if (root == null || node1 == null || node2 == null) { return null; } int depth1 = findTheDepthOfTheNode(root, node1, node2); if (depth1 == -1) { return node2.parentNode; } int depth2 = findTheDepthOfTheNode(root, node2, node1); if (depth2 == -1) { return node1.parentNode; } //p指向较深的节点q指向较浅的节点 NewBinaryTreeNode p = depth1 > depth2 ? node1 : node2; NewBinaryTreeNode q = depth1 > depth2 ? node2 : node1; int depth = Math.abs(depth1 - depth2); while (depth > 0) { p = p.parentNode; depth--; } while (p != q) { p = p.parentNode; q = q.parentNode; } return p; } //求node1的深度,如果node1和node2在一条路径上,则返回-1,否则返回node1的深度 public static int findTheDepthOfTheNode(NewBinaryTreeNode root, NewBinaryTreeNode node1, NewBinaryTreeNode node2) { int depth = 0; while (node1.parentNode != null) { node1 = node1.parentNode; depth++; if (node1 == node2) { return -1; } } return depth; }}
普通的树
同样可以看作是链表的问题,不过由于没有指向父节点的引用,因此不能由下往上进行,但是同样可以看成两条包含目标节点的问题,即求两条链表的最后公共结点问题,使用辅助栈存储包含目标节点的路径,即可完成:
//转换成为求两个链表的最后公共结点问题public class CommonBinaryNode { //BinaryTreeNode是同包中的public类,可以直接使用其数据结构 public static BinaryTreeNode getLowestCommonAncestor2(BinaryTreeNode root, BinaryTreeNode node1, BinaryTreeNode node2){ if(root == null || node1 == null || node2 == null){ return null; } Stack<BinaryTreeNode> path1 = new Stack<BinaryTreeNode>(); boolean flag1 = getThePathOfTheNode(root, node1,path1); if(!flag1){//树上没有node1节点 return null; } Stack<BinaryTreeNode> path2 = new Stack<BinaryTreeNode>(); boolean flag2 = getThePathOfTheNode(root, node2,path2); if(!flag2){//树上没有node2节点 return null; } if(path1.size() > path2.size()){ //让两个路径等长 while(path1.size() != path2.size()){ path1.pop(); } }else{ while(path1.size() != path2.size()){ path2.pop(); } } if(path1.equals(path2)){//当两个节点在一条路径上时 path1.pop(); return path1.pop(); }else{ BinaryTreeNode p = path1.pop(); BinaryTreeNode q = path2.pop(); while(q != p){ p = path1.pop(); q = path2.pop(); } return p; } } //获得根节点到node节点的路径 public static boolean getThePathOfTheNode(BinaryTreeNode root,BinaryTreeNode node,Stack<BinaryTreeNode> path){ path.push(root); if(root == node){ return true; } boolean found = false; //前序遍历整棵树 if(root.leftNode != null){ found = getThePathOfTheNode(root.leftNode, node, path); } if(!found && root.rightNode != null){ found = getThePathOfTheNode(root.rightNode, node, path); } if(!found){ path.pop(); } return found; }}
1 0
- 求树中两个节点的最低公共父节点
- 求树中两个节点的最低公共祖先
- 树中两个节点的最低公共父节点
- 二叉树中两个节点的最低公共父节点
- 【树】求树中两个节点的最低公共祖先
- 找出二叉树中任意两个节点的最低公共父节点
- 二叉树的最低公共父节点
- 二叉树的最低公共父节点
- 树的两个节点的最低公共祖先
- 二叉树中两节点的最低公共父节点。
- 树中两个节点的最低公共祖先
- 树中两个节点的最低公共祖先
- 找出树中两个节点的最低公共祖先
- 二叉树中查找两个节点的最低公共祖先
- 寻找二叉树两个节点的最低公共祖先(LCA)
- 二叉树两个节点的最低公共最先问题
- 树中两个节点的最低公共祖先
- 剑指offer-树中两个节点的最低公共祖先
- 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法
- delphi 下枚举可用串口
- 从图像处理到图像识别
- window.location.Reload()和window.location.href 区别
- 值得推荐的C/C++框架和库
- 求树中两个节点的最低公共父节点
- 腾讯云CentOS 6.6安装 Nginx
- win7笔记本如何变成无线路由器
- ckeditor4.1.1在jquery ui dialog(模式化窗口)中无法编辑,解决方法!
- 以太网设备工作原理
- 写论文感悟
- 公司项目架构的演变过程
- 一页纸商业计划书 (Business Plan) 模板(转载)
- jboss配置文件配置编码方式,类似于tomcat的server.xml配置编码方式