LCA算法求任意两个节点之间的最小公共祖先(最短路径)
2017-10-20 18:43
513 查看
package com.mams.test; import java.util.ArrayList; import java.util.List; /** * Created by leixingbang on 2017/10/19. * Mail:leixingbang@qiyi.com */ public class TreeNode { @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof TreeNode)) return false; TreeNode treeNode = (TreeNode) o; if (!nodeName.equals(treeNode.nodeName)) return false; return true; } @Override public int hashCode() { return nodeName.hashCode(); } private String nodeName; private List<TreeNode>childLst; public TreeNode(String nodeName, List<TreeNode> childLst) { this.nodeName = nodeName; this.childLst = childLst; } public TreeNode(String nodeName) { this.nodeName = nodeName; this.childLst=new ArrayList<TreeNode>(); } public void addNode(TreeNode node) { this.childLst.add(node); } public String getNodeName() { return nodeName; } public void setNodeName(String nodeName) { this.nodeName = nodeName; } public List<TreeNode> getChildLst() { return childLst; } public void setChildLst(List<TreeNode> childLst) { this.childLst = childLst; } }
package com.mams.test; import java.util.*; /** * Created by leixingbang on 2017/10/20. * Mail:leixingbang@qiyi.com * 该工具用来遍历树所有节点,求最短路径 */ public class TranvesalTreeNodeTool { //记录从根节点到某节点的路径,key为节点的名称,value为路径 private HashMap<String, List<TreeNode>> pathMap = new HashMap<String, List<TreeNode>>(); public void deepFirstSearch(TreeNode node) { Stack<TreeNode> stack = new Stack<TreeNode>(); Stack<TreeNode> pathstack = new Stack<TreeNode>(); stack.push(node); while (!stack.empty()) { TreeNode tempNode = stack.pop(); vist(tempNode, pathstack); //说明该节点有孩子节点 if (tempNode.getChildLst() != null && tempNode.getChildLst().size() > 0) { Iterator<TreeNode> iterator = tempNode.getChildLst().iterator(); while (iterator.hasNext()) { stack.push(iterator.next()); } } } } public void vist(TreeNode node, Stack<TreeNode> pathStack) { //保证新加入pathStack的节点 必须是‘pathStack栈顶节点’的孩子节点 while (pathStack.size() > 0 && !isChild(node, pathStack.peek())) { pathStack.pop(); } pathStack.push(node); addPath(pathStack); //System.out.println("访问:" + node.getNodeName()); if (isLeaf(node)) { //当遇到叶子节点时,打印从根节点到叶子节点的路径 printPath(pathStack); } } public void addPath(Stack<TreeNode> pathStack) { TreeNode top = pathStack.peek(); if (!this.pathMap.containsKey(top.getNodeName())) this.pathMap.put(top.getNodeName(), new ArrayList(pathStack)); } public List<TreeNode> getRootToNodePath(String name) { return this.pathMap.get(name); } public static boolean isChild(TreeNode node, TreeNode nodeParent) { if (nodeParent.getChildLst() != null && nodeParent.getChildLst().size() > 0 && nodeParent.getChildLst().contains(node)) return true; else return false; } /** * 打印路径 * @param pathStack */ public static void printPath(Stack<TreeNode> pathStack) { Iterator<TreeNode> iterator = pathStack.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next().getNodeName() + "->"); } System.out.println(); } /** * 打印路径 * @param pathLst */ public static void printPath(List<TreeNode> pathLst) { Iterator<TreeNode> iterator = pathLst.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next().getNodeName() + "->"); } System.out.println(); } public static boolean isLeaf(TreeNode node) { if (node.getChildLst() == null || node.getChildLst().size() <= 0) return true; else return false; } /** * 由于一个孩子节点只有一个父节点,所以从根节点到某一节点的路径是单向且唯一的。如果两个节点有公共的祖先,两个路径合起来应该是倒立的Y字形, * 如A、B两个节点所示,从根节点开始遍历两条不同的路径,当路径出现不一致时(X节点),出现不一致之前的那个点就是最小公共父亲节点 * * X * * * * A * * B * * * @param lst1 * @param lst2 * @return */ public TreeNode getLeastParentNode(List<TreeNode> lst1, List<TreeNode> lst2) { List<TreeNode> loogerLst = lst2; List<TreeNode> shorterLst = lst1; if (loogerLst.size() < shorterLst.size()) { List<TreeNode> tempLst = loogerLst; loogerLst = shorterLst; shorterLst = tempLst; } int index = 0; for (int i = 0; i < shorterLst.size(); i++) { if (shorterLst.get(i).equals(loogerLst.get(i))) continue; else { index = i - 1; break; } } return shorterLst.get(index); } public static void main(String[] args) { TreeNode A = new TreeNode("A"); TreeNode B = new TreeNode("B"); TreeNode C = new TreeNode("C"); TreeNode D = new TreeNode("D"); TreeNode E = new TreeNode("E"); TreeNode F = new TreeNode("F"); TreeNode H = new TreeNode("H"); A.addNode(B); A.addNode(C); B.addNode(D); B.addNode(E); C.addNode(F); D.addNode(H); TranvesalTreeNodeTool tranvesalTreeNodeTool = new TranvesalTreeNodeTool(); tranvesalTreeNodeTool.deepFirstSearch(A); printPath(tranvesalTreeNodeTool.getRootToNodePath("E")); printPath(tranvesalTreeNodeTool.getRootToNodePath("H")); TreeNode x = tranvesalTreeNodeTool.getLeastParentNode(tranvesalTreeNodeTool.getRootToNodePath("E"), tranvesalTreeNodeTool.getRootToNodePath("H")); System.out.println(x.getNodeName()); } }
相关文章推荐
- 求一颗不含指向父节点指针的普通树中任意两个结点的最近公共祖先(O(N*N) 和 O(N) 算法)
- 弗洛伊德算法得到图中任意两个顶点之间的最短路径
- 求二叉树中两个节点的最小公共祖先(LCA)
- 二叉树系列——二叉树中任意两个节点之间的最短路径
- 在二叉树中,求任意两个节点的最近公共祖先(遍历的应用算法)
- LCA问题:求二叉树中任意两个节点的最近公共祖先
- 面试题50 树中两个节点的最低公共祖先LCA(Lowest Common Ancestor )
- 给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。
- 寻找二叉树两个节点的最低公共祖先(LCA)
- 从点对中构建二叉树,并查找两个节点所对应的最小公共祖先
- 二叉树系列——路径系列:打印二叉树两个子节点之间的路径以及最低公共祖先
- LCA问题的Tarjan 脱机最小公共祖先算法
- 【算法面试题】寻找二叉搜索树中两个节点的最近公共祖先节点(转)
- 采用邻接表存储结构,编写一个判别无向图中任意给定的两个顶点之间是否存在一条长度为k的简单路径的算法。
- 树——树中两个节点的最低公共祖先LCA
- 二叉树 最近祖先lca + 两个结点的最小路径
- 树中两个节点最低公共祖先系列算法
- 每天学习一算法系列(29)(有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小)
- 一颗普通的二叉树,如何寻找两个节点的最低公共祖先(发现的一个与算法无关的引用问题)
- lca倍增 算法 最小公共祖先