华为机试---火眼金睛

来源:互联网 发布:淘宝黑号会有什么后果 编辑:程序博客网 时间:2024/04/29 22:12

题目描述

现在我们需要查出一些作弊的问答社区中的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。

输入例子:
31 1 22 1 13 2 1 2

输出例子:
3

1 2 3

题目分析:1.输出要求第一行 为作弊ID数量,第二行开始从小到大每行一个作弊ID,选择TreeSet(有序集合)保存作弊人的ID2.一个问题可能有多人回答,HashSet保存回答问题的ID3.输入第一行为总问题数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 所有回答人的IDHashMap<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]);//提问人的IDint answerNum = Integer.parseInt(str[1]);//回答人数//保存回答人的IDHashSet<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);}}}

1 0
原创粉丝点击