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

Posted wen-pan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    

以上是关于java数据结构与算法之最近公共祖先问题的主要内容,如果未能解决你的问题,请参考以下文章

算法详解之最近公共祖先(LCA)

『图论』LCA 最近公共祖先

『图论』LCA最近公共祖先

二叉树之最近公共祖先LCA

最近公共祖先

算法树上公共祖先的Tarjan算法