作者:亚S哥_271 | 来源:互联网 | 2023-01-25 15:23
给定二叉树中的任意两点,求解该两点的最近公共父节点。程序大致分为递归和非递归两种方式,下面我们先来认识非递归的方式。非递归程序总体的思路:用一种常见高效的数据结构来记录下二叉树中的结
给定二叉树中的任意两点,求解该两点的最近公共父节点。程序大致分为递归和非递归两种方式,下面我们先来认识非递归的方式。
非递归
程序总体的思路:用一种常见高效的数据结构来记录下二叉树中的结构关系,由于是找父节点,所以要用子节点来查找父节点,我们这里用到的是HashMap来进行树形关系的存储。接下来就是先列出一个要求节点的所有父节点,然后比较另一个要求节点的父节点在不在上面的列中,第一个出现的节点,就是我们要求的祖先节点。具体代码如下:
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
Map<TreeNode, TreeNode> parent = new HashMap<>();
Queue<TreeNode> queue = new LinkedList<>();
parent.put(root, null);
queue.add(root);
while (!parent.containsKey(p) || !parent.containsKey(q)) {
TreeNode node = queue.poll();
if (node != null) {
parent.put(node.left, node);
parent.put(node.right, node);
queue.add(node.left);
queue.add(node.right);
}
}
Set<TreeNode> set = new HashSet<>();
while (p != null) {
set.add(p);
p = parent.get(p);
}
while (!set.contains(q)) {
q = parent.get(q);
}
return q;
}
下面来看递归求解过程(只需要抓住一点,两个节点要么在左子树上,要么在右子树上,root就更简单了):
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) {
return root;
}
TreeNode l = lowestCommonAncestor(root.left, p, q);
TreeNode r = lowestCommonAncestor(root.right, p, q);
return l != null && r != null?root : l == null?r: l;
}
这个代码写的也是没谁了,尤其是最后的return,只能膜拜一下了,解释一下最后的一句返回:首先,判断左右子树,如果有空,则返回左子树,原因是在递归程序中,先求解的左子树的节点;如果左右都不为空,则返回他们的父节点,则这个节点,就应该是结果;后面又加了一个三目运算符,原因是,上面返回的左子树有可能为null,比如两个节点都在root的右子树上,那么当左子树为空时,则返回右子树;