树中两个节点的最低公共祖先(Java实现)

xiaoxiao2021-02-27  190

题目:求树中两个结点的最低公共祖先

分析:其实这是一组题目,考官没有说清楚树的结构,那么做法就不尽相同。

比如,如果是二叉搜索树的话,我们只需从根结点判断,如果二结点与根的左右子树比较一大一小,那么跟结点就是二者最低公共祖先;如果二结点都比左子结点小,向左子树递归进行比较;如果二结点都比右子树结点大,向右子树递归进行比较;

如果不是二叉搜索树,但带有指向父节点的指针,那么此题转换成在两个有相交的链表上求第一个相交点。

如果不带指向父节点的指针,那么我们可以记录从根结点到这两个结点的路径即可求出。

以下代码是:普通树(多个子树),子树没有指向父节点的指针

package go.jacob.day520; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import javax.management.RuntimeErrorException; public class Demo1 { public static void main(String[] args) { test01(); System.out.println("=========="); test02(); System.out.println("=========="); test03(); } // 形状普通的树 // 1 // / \ // 2 3 // / \ // 4 5 // / \ / | \ // 6 7 8 9 10 public static void test01() { TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); TreeNode n4 = new TreeNode(4); TreeNode n5 = new TreeNode(5); TreeNode n6 = new TreeNode(6); TreeNode n7 = new TreeNode(7); TreeNode n8 = new TreeNode(8); TreeNode n9 = new TreeNode(9); TreeNode n10 = new TreeNode(10); n1.children.add(n2); n1.children.add(n3); n2.children.add(n4); n4.children.add(n6); n4.children.add(n7); n3.children.add(n5); n5.children.add(n8); n5.children.add(n9); n5.children.add(n10); System.out.println(getLastCommonParent(n1, n9, n10)); } // 树退化成一个链表 // 1 // / // 2 // / // 3 // / // 4 // / // 5 private static void test02() { TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); TreeNode n4 = new TreeNode(4); TreeNode n5 = new TreeNode(5); n1.children.add(n2); n2.children.add(n3); n3.children.add(n4); n4.children.add(n5); System.out.println(getLastCommonParent(n1, n4, n5)); } // 树退化成一个链表,一个结点不在树中 // 1 // / // 2 // / // 3 // / // 4 // / // 5 private static void test03() { TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); TreeNode n4 = new TreeNode(4); TreeNode n5 = new TreeNode(5); TreeNode n6 = new TreeNode(6); n1.children.add(n2); n2.children.add(n3); n3.children.add(n4); n4.children.add(n5); System.out.println(getLastCommonParent(n1, n5, n6)); } /* * 获取两个节点的最低公共祖先 */ public static TreeNode getLastCommonParent(TreeNode root, TreeNode p1, TreeNode p2) { //path1和path2分别存储根节点到p1和p2的路径(不包括p1和p2) List<TreeNode> path1 = new ArrayList<TreeNode>(); List<TreeNode> path2 = new ArrayList<TreeNode>(); List<TreeNode> tmpList = new ArrayList<TreeNode>(); getNodePath(root, p1, tmpList, path1); getNodePath(root, p2, tmpList, path2); //如果路径不存在,返回空 if (path1.size() == 0 || path2.size() == 0) return null; return getLastCommonParent(path1, path2); } // 获取根节点到目标节点的路径 public static void getNodePath(TreeNode root, TreeNode target, List<TreeNode> tmpList, List<TreeNode> path) { //鲁棒性 if (root == null || root == target) return; tmpList.add(root); List<TreeNode> children = root.children; for (TreeNode node : children) { if (node == target) { path.addAll(tmpList); break; } getNodePath(node, target, tmpList, path); } tmpList.remove(tmpList.size() - 1); } //将问题转化为求链表最后一个共同节点 private static TreeNode getLastCommonParent(List<TreeNode> p1, List<TreeNode> p2) { TreeNode tmpNode = null; for (int i = 0; i < p1.size(); i++) { if (p1.get(i) != p2.get(i)) break; tmpNode = p1.get(i); } return tmpNode; } // 节点类 private static class TreeNode { int val; List<TreeNode> children = new ArrayList<>(); public TreeNode(int val) { this.val = val; } @Override public String toString() { return val + ""; } } } 点击打开链接

转载请注明原文地址: https://www.6miu.com/read-14349.html

最新回复(0)