## node1 和 node2 的最低公共祖先节点
### 第一种简单 暴力 的方法,遍历整颗树,使用map 把每个节点自己的父节点保存,key是node, value是父node
然后把node1 往上 遍历找自己的祖辈,保存在set 里,
然后node2 往上遍历,如果找到第一个在 node1 的set里的node,这个node就是最低公共祖先节点
```java
public static Node findLowestCommonAncestor(Node head, Node node1, Node node2) {
if (head == null || head == node1 || head == node2) {
// base case
return head;
}
// 使用map保存每个节点的父节点
HashMap<Node, Node> fatherMap = new HashMap<>();
// 根节点的父节点 null
fatherMap.put(head, null);
// 遍历树,找到每个节点的父节点
findEachNodeFather(head, fatherMap);
// 找node 1 的祖祖辈辈,保存在set中
HashSet<Node> node1Set = new HashSet<>();
Node curFather = fatherMap.get(node1);
while (curFather != null) {
node1Set.add(curFather);
curFather = fatherMap.get(curFather);
}
Node cur2Father = fatherMap.get(node2);
while (cur2Father != null) {
if (node1Set.contains(cur2Father)) {
return cur2Father;
}
}
return null;
}
```
```java
private static void findEachNodeFather(Node head, HashMap<Node, Node> fatherMap) {
if (head == null) {
return;
}
// 看自己有没有左节点
if (head.left != null) {
fatherMap.put(head.left, head);
}
if (head.right != null) {
fatherMap.put(head.right, head);
}
findEachNodeFather(head.left, fatherMap);
findEachNodeFather(head.right, fatherMap);
}
```
### 第二种方法,分俩种情况
1) node1是node2 的祖先, 或者 node2 是node 1 的祖先
2) node 1 和 node2 不互为祖先
```java
public static Node findLowestCommonAncestor_02(Node head, Node node1, Node node2) {
if (head == null || head == node1 || head == node2) {
// base case
return head;
}
// 获取 左子树 返回的 node
// 可能是 null, 可能是 node 1 可能是 node2
Node left_return_node = findLowestCommonAncestor_02(head.left, node1, node2);
// 获取 右子树 返回的 node
// 可能是 null, 可能是 node 1 可能是 node2
Node right_return_node = findLowestCommonAncestor_02(head.right, node1, node2);
// 情况1: 如果左子树和右子树都返回null,不考虑
// 情况2: 左子树 和 右子树 都不为null, 那就说明当前节点就是 最低公共祖先
if (left_return_node != null && right_return_node != null) {
return head;
}
// 情况3:左子树 返回 不为空,说明 node 1 和 node 2 必有一个在左子树。
if (left_return_node != null) {
// 左子树 只有 1个节点,返回 left_return_node 没问题
// 左子树 有 俩个节点,说明 是互为祖先的情况,
// 不考虑 right_return_node ,是因为情况2 已经在前面判断了,如果俩个都不为空,
return left_return_node;
}
// 情况4: 左子树返回 空,说明 node 1 和node 2都在右子树 。,情况3 的左子树的 镜像 就是 右子树 。
if (left_return_node == null) {
return right_return_node;
}
return null; //走不到这。如果走到这,说明不在一颗数上。
}
```
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探