集合合并

集合合并

题目描述

给定若干个32位int数字集合,每个集合中的数字无重复,譬如:
{1,2,3} {2,5,6} {8}
将其中交集不为空的集合合并,保证合并完成后所有集合之间无交集,输出合并后的集合个数以及最大集合中元素的个数。

输入描述:

输入格式:

  1. 第一行为一个数字N,表示集合数。
  2. 接下来N行,每行一个非空集合,包含若干个数字,数字之间用空格分开。
    假设第i个集合的大小为Si,数据满足N<=100000,ΣSi<=500000

输出描述:

输出格式:

  1. 第一行为合并后的集合个数。
  2. 第二个为最大集合中元素的个数

解题思路

1.当两集合不存在共同元素

2.当两集合存在一个共同元素时,将L1的指针指向L2,并且将ary_L[1]融合到ary_L[2],元素所在的集合也更新为在L3;
在这里插入图片描述
3.当两集合存在两个共同元素时,发现L1的指针P已经指向L2, 表示ary_L[2]已经融合了集合L1,并将元素所在的集合设定在L2, 跳过该元素继续下一个循环.
在这里插入图片描述
4.当集合L3和L1有共同元素, L1和L2也有共同元素时,将L1、L2的P指针更新指向L3,并将ary_L[2]融合到ary_L[3],并将元素所在集合更新到L3;
在这里插入图片描述
5.当集合L3和L1、L2有共同元素, L1和L2也有共同元素时,

  1. 若先查询到L3和L1有共同元素,L1将L1、L2的P指针更新指向L3,并将ary_L[2]融合到ary_L[3];紧接着查询到L3和L2有共同元素,发现L2的P指针已经指向L3,表示已经融合,跳过;
  2. 若先查询到L3和L2有共同元素,L1将L1、L2的P指针更新指向L3,并将ary_L[2]融合到ary_L[3];紧接着查询到L3和L1有共同元素,发现L1的P指针已经指向L3,表示已经融合,跳过;

图略

代码

import java.io.*;

public class Main {
    public static void main(String[] args)throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int cur_n = n;//当前集合数
        int max = 0;//最大集合中的元素个数
        int total = 20000000;//要超过32位所能表示的最大数
        int[] ele2ary = new int[total];//元素当前所在集合
        int[] ary_L = new int[n+1];//当前集合n的长度
        int[] ary2p = new int[n+1];//集合n所指向的集合
        for(int i=1;i<=n;i++){
            String[] elist = br.readLine().split(" ");
            for(int j=0;j<elist.length;j++){
                int ele = Integer.parseInt(elist[j]);
                if(ele2ary[ele]==0){
                    ele2ary[ele]=i;
                    ary_L[i]++;
                    // max = Math.max(max, ary_L[i]);
                }else{
                    int bf = ele2ary[ele]; //当前元素上次存在的集合
                    ele2ary[ele] = i; //更新当前元素所在集合
                    while(ary2p[bf]!=0){ //找出元素所在的集合或者合并后的集合,并且将合并集合的各个集合指向当前集合
                        if(bf==ary2p[bf]) break;//判断是否指向自己
                        int temp = bf;
                        bf = ary2p[bf];
                        ary2p[temp] = i;
                    }
                    if(bf!=i){
                        ary_L[i]+=ary_L[bf];
                        //max = Math.max(max, ary_L[i]);
                        cur_n--;
                        ary2p[bf] = i;//更新最后一个集合,使其,=指向当前集合
                    }
                }
                max = Math.max(max, ary_L[i]);
            }
        }
        System.out.println(cur_n);
        System.out.println(max);
    }        
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值