java面试代码题:查并集

查并集

题目如下:

  • 如今有11个元素(1-10),我们设置一定的规则,例如输入<a,b>,则代表a,b属于一个集合,若此时还有规则输入<b,c>,则代表a,b,c属于同一个集合。
  • 首先给定一系列的规则输入<a,b>,规定集合分布。
  • 最后输入测试样例<x,y>,判断x,y是否属于一个集合

思路如下:

首先我们定义一个friendMap,其中存储:<x,y>表示x的根节点是y
首先存储以下内容:

  • <1,1>,<2,2> ~~~~~~<10,10>

表示此时每一个元素的根节点都是自己,即每一个元素都是一个独立的集合。

//定义有10个元素
int[] data = new int[]{1,2,3,4,5,6,7,8,9,10};

 HashMap<Integer,Integer> friendMap = new HashMap<>();
//先定义每元素的父节点都是自己
for(int i = 0; i < data.length; i++) friendMap.put(data[i],data[i]);

之后我们输入<a,b>进行合并集操作:即输入a,b元素,找到a元素的根节点,同时找到b元素的根节点,将其进行合并。

public static void merge(HashMap<Integer,Integer> friendMap, int a, int b){
        int friendRoota = getRoot(friendMap,a);
        int friendRootb = getRoot(friendMap,b);

        //找到两个元素的根节点,将这两个根节点合并 合并的顺序可以颠倒
        if(friendRoota != friendRootb){
            friendMap.put(friendRootb,friendRoota);
        }
    }

例如此时输入:<2,5>

  • friendRoota = 2;
  • friendRootb = 5;
  • 此时将map中的<5,5> 修改为<5,2>,这就代表5的根节点是2

此时map中存的的元素是:
<1,1> <2,2> <5,2>等等

例如此时输入:<1,5>

  • friendRoota = 1;
  • friendRootb = 2;
  • 此时将map中的<2,2> 修改为 <2,1>,这就代表2的根节点是1

此时map中存的元素是:
<1,1> <2,1> <5,2>等等

所以此时其实可以发现其实我们将5 ——> 2——> 1 生成了一课树,这就类似于将这三个元素变成了一个集合,并且是有关联的。但是实际上,我们的map中最好将value变为key的根root,而不是像此时5存储的value是2,并不是根root:1。

因此在getRoot()方法中我们不仅要返回元素的根root,并且每次都需要将元素的value修改为根root,因此方法如下:

public static int getRoot(HashMap<Integer,Integer> friendMap, int num){

    if(friendMap.get(num) == num){
        return num;
    }

    //我们在查找的时候如果发现其中有元素是一个并集的 但是此时他的根节点还未来得及修改,那么就进行修改
    //及每次经过一次查找,这个并集中的所有元素的value都会指向根root节点(这个并集的根)
    int temp = getRoot(friendMap,friendMap.get(num));
    friendMap.put(num,temp);
    return temp;

}

全部代码如下:


import java.util.HashMap;

public class test2 {


    public static void main(String[] args) {

        //定义有10个元素
        int[] data = new int[]{1,2,3,4,5,6,7,8,9,10};

        HashMap<Integer,Integer> friendMap = new HashMap<>();
        //先定义每元素的父节点都是自己
        for(int i = 0; i < data.length; i++) friendMap.put(data[i],data[i]);

        //开始合并元素
        int[][] friends = new int[][]{{2,5},{1,5}};
        for(int i = 0; i < friends.length; i++){
            merge(friendMap,friends[i][0],friends[i][1]);
        }


        //测试
        int[][] nums = new int[][]{{1,5}};
        for(int i = 0; i < nums.length; i++){
            int i1 = getRoot(friendMap, nums[i][0]);
            int i2 = getRoot(friendMap, nums[i][1]);
            if(i1 == i2) System.out.println("true");
            else System.out.println("false");
        }
        System.out.println();

    }


    public static void merge(HashMap<Integer,Integer> friendMap, int a, int b){
        int friendRoota = getRoot(friendMap,a);
        int friendRootb = getRoot(friendMap,b);

        //找到两个元素的根节点,将这两个根节点合并 合并的顺序可以颠倒
        if(friendRoota != friendRootb){
            friendMap.put(friendRootb,friendRoota);
        }
    }

    public static int getRoot(HashMap<Integer,Integer> friendMap, int num){

        if(friendMap.get(num) == num){
            return num;
        }

        //我们在查找的时候如果发现其中有元素是一个并集的 但是此时他的根节点还未来得及修改,那么就进行修改
        //及每次经过一次查找,这个并集中的所有元素的value都会指向根root节点(这个并集的根)
        int temp = getRoot(friendMap,friendMap.get(num));
        friendMap.put(num,temp);
        return temp;

    }



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值