java数据结构与算法之最近公共祖先问题

①、问题描述

给你两个节点node1,node2,这两个节点都在树上,再给你一个节点head,head表示二叉树的头节点,请返回他们【最近的公共祖先】

②、核心点分析

  • 如果我们能顺着某个node向上找到他的父亲节点就好了。如果能从某个节点开始向上找到他的parent节点,那么这个题就和单链表相交问题一样了,变得非常简单了
  • 所以,对于这种二叉树结构,我们只要知道【二叉树的头节点】,那么我们就可以【遍历】这棵二叉树。然后利用【HashMap结构】来存放每个节点的父子关系,这样的话,对于每一个节点,我们都可以找到他的父节点了
  • 所以这个题,可以【巧妙的利用hash表来存放树节点的父子关系】,将二叉树问题转换为了单链表相交问题。
③、代码
public class LowestCommonAncestor {

  	// 测试代码
    public static void main(String[] args) {
        TreeNode head = new TreeNode("1");
        head.left = new TreeNode("2");
        head.right = new TreeNode("3");
        head.left.left = new TreeNode("4");
        head.left.right = new TreeNode("5");
        head.right.left = new TreeNode("6");
        head.right.right = new TreeNode("7");
        head.right.right.left = new TreeNode("8");

        TreeNode o1 = head.left.right;
        TreeNode o2 = head.right.left;

        System.out.println("o1 : " + o1.val);
        System.out.println("o2 : " + o2.val);
        System.out.println("ancestor : " + findLowestCommonAncestor(o1, o2, head).val);
        System.out.println("===============");
    }

    /**
     * 给你两个节点node1,node2,这两个节点都在树上,再给你一个节点head,head表示二叉树的头节点,请返回他们最近的公共祖先
     */
    public static TreeNode findLowestCommonAncestor(TreeNode node1, TreeNode node2, TreeNode head) {
        // 非法数据,没有公共祖先
        if (node1 == null || node2 == null || head == null) {
            return null;
        }
        if (node1 == node2) {
            return node1;
        }
        // 先将父子关系保存到map中
        HashMap<TreeNode, TreeNode> parentMap = new HashMap<>();
        // 用先序遍历的方式保存各个节点的父子关系
        Stack<TreeNode> stack = new Stack<>();
        stack.push(head);
        while (!stack.isEmpty()) {
            TreeNode pop = stack.pop();
            // 先压右再压左
            if (pop.right != null) {
                parentMap.put(pop.right, pop);
                stack.push(pop.right);
            }
            if (pop.left != null) {
                parentMap.put(pop.left, pop);
                stack.push(pop.left);
            }
        }

        HashSet<TreeNode> set = new HashSet<>();
        // 从node1节点开始,一直向上找他的父节点,并保存到set中
        TreeNode cur = node1;
        while (cur != null) {
            set.add(cur);
            cur = parentMap.get(cur);
        }

        // 从node1节点开始,依次找他的父节点
        cur = node2;
        while (cur != null) {
            // 第一个contains的节点就是他们最近的公共祖先,类似于单链表相交问题
            if (set.contains(cur)) {
                return cur;
            }
            cur = parentMap.get(cur);
        }

        // 没有公共祖先
        return null;
    }
}

@Data
class TreeNode {
    String val;
    TreeNode left;
    TreeNode right;

    public TreeNode(String val) {
        this.val = val;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值