1229:最短公共祖先问题

博客指出在连通分量合并时存在的问题,当至少含2个结点的连通分量X合并到其他连通分量时,未更新X所有结点的深度值;而只含一个结点的连通分量X合并时不存在此问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有一种情况暂未解决,当一个至少含2个结点的连通分量X,要合并到另外的连通分量上去的情况:

没有更新X的所有结点的深度值。

但当只含一个结点的连通分量X,要合并到另外的连通分量上去的情况,不存在问题。

package com.example.kevintest.demo.zx;

import java.util.HashMap;
public class Test2 {

    //保存节点i的高度
    static HashMap<String , Integer> high = new HashMap<>();

    /*
    * 判断是否有连通
    * */
    public static boolean checkIsConnect(HashMap<String , String> h , String p1 , String p2) {
        String bossP1 = findBoss(h , p1);
        String bossP2 = findBoss(h , p2);
        return bossP1 == bossP2;
    }

    /*
    * 查找p的最大boss
    * */
    public static String findBoss(HashMap<String , String> h , String p) {
        while(true) {
            if(h.get(p) == null) {
                return p;
            }
            p = h.get(p);
        }
    }

    /*
    * 是否是直系关系
    * */
    public static int isZX(HashMap<String , String> h , String p1 , String p2) {
        int len = 0;
        int isok = 0;
        String tmp_p1 = p1;
        while(true) {
            if(h.get(p1) == null) {
                break;
            }
            if(h.get(p1) == p2) {
                isok = 1;
                break;
            } else {
                p1 = h.get(p1);
                len++;
            }
        }
        if(isok == 1) {
            return len+1;
        } else {
            //归位
            p1 = tmp_p1;
            len = 0;
            while(true) {
                if(h.get(p2) == null) {
                    break;
                }
                //System.out.println(h.get(p2));
                if(h.get(p2) == p1) {
                    isok = 1;
                    break;
                } else {
                    p2 = h.get(p2);
                    len++;
                }
            }
            if(isok == 1) {
                return len+1;
            } else {
                return -1;
            }
        }
    }

    /*
    * 获得p1和p2的关系
    * */
    public static Object GetGeneration(HashMap<String , String> h , String p1 , String p2) {
        //有直系连接
        int len = isZX(h , p1 , p2);
        if(len != -1) {
            return len;
        }
        //不是直系[包含两种情况:1.根本就不连通; 2.虽无直系但有共同祖先]
        if(!checkIsConnect(h , p1 , p2)) {
            return -1;
        }
        return GetCousin(h , p1 , p2) + " " + Math.abs(high.get(p1) - high.get(p2));
    }


    /*
    * M代
    * */
    public static int GetCousin(HashMap<String , String> h , String p1 , String p2) {
        //深的在右边的情况,交换一下。high左>high右
        if(p1.compareTo(p2) < 0) {
            String t = p1;
            p1 = p2;
            p2 = t;
        }
        //相差的深度
        int sub = Math.abs(high.get(p1) - high.get(p2));
        //较深的向上移动到和右子树相同高度
        for(int i=0;i<sub;i++) {
            p1 = h.get(p1);
        }
        int LCALen = 0;
        while(true) {
            if(h.get(p1) == h.get(p2)) {
                break;
            }
            p1 = h.get(p1);
            p2 = h.get(p2);
            LCALen++;
        }
        return LCALen;
    }


    /*
    * HashMap<儿子,父亲>
    * */
    public static void AddRelationShip(HashMap<String , String> h , String parent , String child) {
        h.put(child , parent);
        //给高度赋值
        if(high.get(parent) == null) {
            if(high.get(child) == null) {
                //第一次构建该连通分量
                high.put(parent , 1);
                high.put(child , 0);
            } else {
                //在已有的连通分量[上面]加节点,高度+1
                high.put(parent , high.get(child) + 1);
            }
        } else {
            //在已有的连通分量[下面]加节点,高度-1
            high.put(child , high.get(parent) - 1);
        }
    }


    public static void main(String[] args) {
        HashMap<String , String> h = new HashMap<>();

        AddRelationShip(h , "Don" , "Fred" );
        AddRelationShip(h , "Bill" , "John");
        AddRelationShip(h , "Fred" , "Jack");
        AddRelationShip(h , "Fred" , "Fran");
        AddRelationShip(h , "Jack" , "Phil");
        AddRelationShip(h , "Eric" , "Sun");
        AddRelationShip(h , "Don" , "Bill" );

        System.out.println(GetGeneration(h , "Don" , "Bill"));   // 1
        System.out.println(GetGeneration(h , "Sun" , "Jack"));   // -1
        System.out.println(GetGeneration(h , "John" , "Jack"));   //1 0
        System.out.println(GetGeneration(h , "Phil" , "Fred"));   //2
        System.out.println(GetGeneration(h , "Phil" , "John"));   //1 1
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值