clllll  

## 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; //走不到这。如果走到这,说明不在一颗数上。

}
```
 
 
 
 

 

posted on   llcl  阅读(67)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
 
点击右上角即可分享
微信分享提示