求解二叉树两个节点的最小公共父节点

题目描述

给定一颗二叉树和两个任意节点,请求解出这两个节点的最小公共父节点,如果其中一个节点本身是另外一个的父类,那么就返回这个父节点,否则,就返回距离他们俩最近的公共父节点。此题给定的两个节点肯定在这颗二叉树中。

思路分析

常规思路,二叉树只能从父节点到孩子节点遍历,从孩子节点往上回溯比较困难,因此,此题既然要求求出最小公共父节点,那么,就构造一个从孩子节点回溯父节点的数据结构,用map保存孩子节点对应的父节点。
然后,从给定的两个节点中的任意一个开始向上回溯父节点,将路径上的所有节点都放入set中,然后,再回溯另一个,每遍历到一个父节点就在set中查找是否存在,返回找到的第一个节点,就是最小公共父节点。

代码

public static Node get(Node head,Node n1,Node n2){
        HashMap<Node,Node> map=new HashMap<>();
        map.put(head,head);
        getMap(map,head);
        HashSet<Node> set=new HashSet<>();
        while (n1!=head){
            set.add(n1);
            n1=map.get(n1);
        }
        set.add(head);
        while (true){
            if(set.contains(n2)){
                return n2;
            }else {
                n2=map.get(n2);
            }
        }
    }

    private static void getMap(HashMap map,Node node) {
        if(node==null){
            return;
        }
        Node left=node.left;
        Node right=node.right;
        if(left!=null){
            map.put(left,node);
        }
        if(right!=null){
            map.put(right,node);
        }
        getMap(map,left);
        getMap(map,right);
    }

思路二

总体思路是想利用递归向上返回的值来返回最小公共父节点。
分析题目的两种情况:
情况一:n1或者n2本身是另一个的父类节点,那么,最终结果应该是这个父节点本身。因此,向上返回的数据,返回它本身就可以了,如果它下面有另一个,也返回它自己本身就行,这样就会把下面的覆盖掉。然后,其余节点,如果不是n1和n2,就返回null,如果接收的返回值包含n1或者n2,就继续向上传递。
情况二:n1和n2本身没有父子关系,他们有一个公共的父节点,那么,向上传递的信息,n1或者n2就传递他们本身,但是,和上面有一点不同的地方在于,其余节点,有可能接收的返回值包含n1和n2两个,那么,其实这个节点就是最小的公共父类节点,因此,如果接收的左右孩子分别为n1和n2,那么,就返回他自己本身。其余节点还是接收什么就原样向上返回。
因此,总结一下上面分析的结果,向上返回的数据:
本身为n1或者n2,就向上返回自己
接收两个的话,就返回自己
如果接收一个,就原样照抄返回
自己不是n1和n2,且没有接收,就返回null

代码

    public static Node getFather(Node node,Node n1,Node n2){
        if(node==null||node==n1||node==n2){
            return node;
        }
        Node left=getFather(node.left,n1,n2);
        Node right=getFather(node.right,n1,n2);
        if(left!=null&&right!=null){
            return node;
        }
        return left!=null ? left:right;
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值