腾讯笔试2:通知的互相传递

输入:

N M

3 5 6 1

0 1

2 4 7

3 8 9

输入的N表示一共有几个人(话说这个参数我好想没用到),M表示一共有几个小团体,下面的M行就表示每个小团体里面的人的编号,比如3 5 6 1就表示第0个小团体里面有编号3  5 6  1的人。每个人可以分属于几个不同的团体或者不属于任何团体

一开始会向编号为0的人传达一个消息,然后0会把这个消息传递到所在组里面的每个人,每个人又会传递给他的组里面的每个人,求最后一共有多少人知道这个消息。


思路1:最朴素的思想,我们建立一个idset(一个hashset)保存所有知道消息的人的编号,然后建立一个rowsSet存放已经知道这个消息的小团体(就是行号,防止后面再遍历搜索这一行),然后建立一个队列,所有会知道这个消息的人都会进入这个队列。首先0知道了那么这一行的所有人都会知道,都放入队列。然后不断把队列里面的元素取出来,然后取出不在rowsSet里面的行的元素,都加入这个队列里面。

之所以要这个队列,是因为我们不确定要遍历到什么时候才算结束,因为如果一开始加入 0 1,然后自然要遍历第0行(因为第0行有1),但是第0行的3又出现在第3行,所以我们又需要去遍历第三行的所有元素,如果第三行里面还有个比如x,它又出现在第五行,我们又要去遍历第5行,因此用一个队列把所有需要查找的元素都放进去,最后遍历结束的标志就是队列为空。


	public static int res=0;
	//start表示0所在的行
	public static  HashSet<Integer> idset=new HashSet<>();//存放结果编号
	public static void process(List<List<Integer>> all,int start){
		int number=all.get(start).size();//这一行的数量
		Queue<Integer> queue=new LinkedList<>();
		Set<Integer> rowsSet=new HashSet<>();//存放已有的行编号
		rowsSet.add(start);
		for(int i=0;i<number;i++){
			queue.add(all.get(start).get(i));
		}
		while(!queue.isEmpty()){
			int bianhao=queue.poll();//我们需要找的这个编号
			idset.add(bianhao);
			for(int j=0;j<all.size();j++){//遍历所有行
				if(j!=start){
					if(all.get(j).contains(bianhao)&&!rowsSet.contains(j)){//这一行如果有我们要的编号,并且之前没有遍历
						rowsSet.add(j);
						for(int m=0;m<all.get(j).size();m++){//遍历这一行的所有数字
							int tmp=all.get(j).get(m);//找出第j行的第m个
							if(!idset.contains(tmp)){
								idset.add(tmp);
								queue.add(tmp);
							}	
						}
					}
				}
			}
			
		}
		res=idset.size();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()){
			int n=sc.nextInt();
			int m=sc.nextInt();//小团体的个数
			sc.nextLine();
			List<List<Integer>> all=new ArrayList<>();//小团体都放入all里面
			int start=-1;
			for(int i=0;i<m;i++){
				List<Integer> tmp=new ArrayList<>();
				int count=sc.nextInt();
				for(int j=0;j<count;j++){
					int num=sc.nextInt();
					tmp.add(num);
					if(num==0)
						start=i;//把0所在的行保存
				}
				all.add(tmp);
				sc.nextLine();
			}
			process(all,start);
			System.out.println(res);
		}
	}

上述代码确实略微繁琐,但是却能够100%AC。

扫描二维码关注公众号,回复: 11599541 查看本文章

思路2:并查集

todo

猜你喜欢

转载自blog.csdn.net/qq_35590091/article/details/108441336