华为机试---火眼金睛

题目描述

现在我们需要查出一些作弊的问答社区中的ID,作弊有两种:1.A回答了B的问题,同时B回答了A的问题。那么A和B都是作弊。2.作弊ID用户A和作弊ID用户B同时回答了C的问题,那么C也是作弊。已知每个用户的ID是一串数字,一个问题可能有多个人回答。

输入描述:
每组数据第一行为总问题数N(N小于等于200000),第二行开始每行一个问题,第一个数字为提问人ID,第二个数字为回答人数,后面则为所有回答人的ID。(ID均为0-1000000的整数)


输出描述:
第一行为作弊ID数量,第二行开始为从小到大的每行一个作弊ID。

输入例子:
3
1 1 2
2 1 1
3 2 1 2

输出例子:
3

1 2 3

题目分析: 1.输出要求第一行 为作弊ID数量,第二行开始从小到大每行一个作弊ID,选择TreeSet(有序集合)保存作弊人的ID 2.一个问题可能有多人回答,HashSet保存回答问题的ID 3.输入第一行为总问题数N,第二行开始每行一个问题,   第一个数字为提问人ID,第二个数字为回答人数,后面是所有回答人的ID。使用Map保存信息   key 提问人ID     value 所有回答人的ID

理解两种作弊判断规则:
1.A回答B的问题,同时B回答A的问题,A和B都是作弊,即相互回答问题,两人均作弊
2.作弊的用户A和B同时回答C的问题,C也作弊,即两个或两个以上的作弊用户同时回答,则提问者被判作弊


本题有几个坑:
1.提问者可以回答自己提出的问题,使用规则一判断时候需要加入判断避免陷入死循环
2.可能存在一个ID多次提问,需要将回答者去重合并成一个集合

import java.util.HashMap; import java.util.HashSet; import java.util.Scanner;  import java.util.TreeSet; public class Main { public static void main(String[] args){ Scanner scan = new Scanner(System.in); while(scan.hasNext()){ int N = scan.nextInt();//总问题数             scan.nextLine();//跳过换行符 String[] info = new String[N]; for(int i = 0 ; i < N ; i++){ info[i] = scan.nextLine(); } judgeCheat(info , N); } scan.close();     } private static void judgeCheat(String[] info, int n) { // key 提问人ID     value 所有回答人的ID HashMap<Integer , HashSet<Integer>> infoMap = new HashMap<Integer , HashSet<Integer>>(); // ID从小到大保存作弊者 TreeSet<Integer> cheatTs = new TreeSet<Integer>(); for(int i = 0 ; i < n ;i++){ String[] str = info[i].split(" "); int askId = Integer.parseInt(str[0]);//提问人的ID int answerNum = Integer.parseInt(str[1]);//回答人数 //保存回答人的ID HashSet<Integer> answerSet = new HashSet<Integer>(); for(int j = 0 ; j < answerNum ; j++){ int answerId = Integer.parseInt(str[2 + j]); answerSet.add(answerId); //如果回答人同时也提问题,规则一判断是否作弊 if(askId != answerId && infoMap.containsKey(answerId)){ //获得他对应的回答人ID集合 HashSet<Integer> tempAnswerSet = infoMap.get(answerId); //判断是否在相互回答,如果是两个都是作弊 if(tempAnswerSet.contains(askId)){ cheatTs.add(askId); cheatTs.add(answerId); } } }//endfor in             //如果存在一个ID多次提问,将回答者编号ID重新合并到一个集合中 if(infoMap.containsKey(askId)){ answerSet.addAll(infoMap.get(askId)); } //解析完一行,保存信息 infoMap.put(askId , answerSet); }//endfor out //根据规则二判断是否作弊,有两个或两个以上作弊ID同时回答是作弊 for(Integer key : infoMap.keySet()){ HashSet<Integer> answerIdSet = infoMap.get(key); //用到java取交集函数retainAll //如果存在相同元素,answerIdSet中仅保留相同的元素。如果不存在相同元素,answerIdSet会变为空。 answerIdSet.retainAll(cheatTs); if(answerIdSet.size() >= 2){ cheatTs.add(key); } } System.out.println(cheatTs.size()); for(Integer cheatId : cheatTs){ System.out.println(cheatId); } } }

你可能感兴趣的:(java,华为)