2016奇虎360研发工程师内推笔试编程题:找镇长
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016奇虎360研发工程师内推笔试编程题:找镇长相关的知识,希望对你有一定的参考价值。
360员工桂最近申请了一个长假,一个人背着包出去自助游了。
路上,他经过了一个小镇,发现小镇的人们都围在一棵树下争吵。桂上前询问情况,得知小镇的人们正缺一个镇长,他们希望能选一个知名又公正的镇长,即,大家希望能选出一个人,所有人都认识他,但同时他不认识镇上除自己以外的其他人(在此,我们默认每个人自己认识自己)。可是小镇里的人太多了,一下子大家谁也说服不了谁。
“这简单啊。”桂表示。于是他一下子统计出来了镇上人们相互之间的认识关系,并且一下子找到了合适的镇长人选。
现在你手上也拿到了这样一份认识关系的清单。其中上面给出的认识关系是单向的,即,A认识B与B认识A是相互独立的,只给出A认识B就不能认为B认识A,例如,我认识你,你不一定认识我。而且,这里的认识关系也不具有传递性,即,A认识B,B认识C,但这不代表A认识C。同时,为了方便处理,这份清单中,镇上的N个人依次编号为1到N。你能否像桂一样快速找到合适的镇长人选呢?
路上,他经过了一个小镇,发现小镇的人们都围在一棵树下争吵。桂上前询问情况,得知小镇的人们正缺一个镇长,他们希望能选一个知名又公正的镇长,即,大家希望能选出一个人,所有人都认识他,但同时他不认识镇上除自己以外的其他人(在此,我们默认每个人自己认识自己)。可是小镇里的人太多了,一下子大家谁也说服不了谁。
“这简单啊。”桂表示。于是他一下子统计出来了镇上人们相互之间的认识关系,并且一下子找到了合适的镇长人选。
现在你手上也拿到了这样一份认识关系的清单。其中上面给出的认识关系是单向的,即,A认识B与B认识A是相互独立的,只给出A认识B就不能认为B认识A,例如,我认识你,你不一定认识我。而且,这里的认识关系也不具有传递性,即,A认识B,B认识C,但这不代表A认识C。同时,为了方便处理,这份清单中,镇上的N个人依次编号为1到N。你能否像桂一样快速找到合适的镇长人选呢?
输入描述:
首先一个正整数T(T≤20),表示数据组数。 之后每组数据的第一行有2个整数n 和m (1≤n≤105 ,0≤m≤3×105 ),依次表示镇上的人数和相互之间的认识关系数。 之后m行,第 i 行每行两个数Ai和Bi (1≤Ai ,Bi ≤n ),表示Ai认识Bi。(保证没有重复的认识关系,但可能存在自己认识自己的认识关系) 保证所有数据中80%的数据满足n≤1000,m≤10000
输出描述:
一共2T 行,每组数据对应2行。 第一行,一个整数,表示你所找出来的合适的镇长人选人数num i 。 第二行,num i 个整数,每两个数中间用空格隔开,表示你所选的合适的镇长的编号。 特别的,如果并没有找到合适的镇长,第一行输出一个数0,第二行留空即可(参见样例)。
输入例子:
3 2 0 3 2 1 2 3 2 4 5 1 1 2 1 3 1 4 1 3 3
输出例子:
0 1 2 1 1
解题
题意:找到其他人都认识他,而他都不认识其他人的那个他
定义人数的矩阵,表示关系
A[i][j] 表示 i 人 与 j人的关系,为 1 的时候表示认识 ,0 不认识,i==j 表示自己认识自己
答案满足:
该 i 行只有 A[i][i] 为1,其他都为 0
该 i 列元素都为 1
1 package a_360; 2 3 import java.util.ArrayList; 4 import java.util.Scanner; 5 6 public class Main{ 7 8 /** 9 * 题目: 10 * 找出别人都认识他,而他其他人都不认识的人 11 * 输入: 12 * T T个这样的测试样例 13 * n m n个人 m个关系数 14 * 下面m行就是关系数 15 * 输出: 16 * 第一行:这样的人有几个 17 * 满足条件人的编号 18 * 19 * 若不存在,输出 0 空格 20 */ 21 public static void main(String[] args) { 22 // TODO Auto-generated method stub 23 Scanner scn = new Scanner(System.in); 24 int T = scn.nextInt(); // 测试数据组数 25 for (int i = 0; i < T; i++) { 26 int n = scn.nextInt(); // 人数 27 int m = scn.nextInt(); // 关系数 28 if(m==0 || n==1){ 29 System.out.println(0); 30 System.out.println(); 31 continue; 32 } 33 int[][] A = new int[n][n]; 34 35 for(int k =0;k<m;k++){ 36 int m1 = scn.nextInt(); 37 int m2 = scn.nextInt(); 38 A[m1-1][m2-1] = 1; 39 } 40 // 对角值为 1 41 for(int k =0;k<n;k++){ 42 A[k][k] = 1; 43 } 44 relation_0(A); 45 } 46 } 47 48 public static void relation_0(int[][] A){ 49 // 关系已经存在二维数组中,找出二维数组中行只有对角位置是1 ,对角位置所在的列都是 1 50 int count = 0; 51 ArrayList<Integer> res = new ArrayList<Integer>(); 52 for(int i = 0;i<A.length;i++){ 53 boolean row1 = true; 54 boolean col1 = true; 55 // 判断第 i列是否都是1 都是1 说明别人都认识他 56 for(int row = 0;row<A.length;row++){ 57 if(A[row][i] == 0){ 58 col1 = false; 59 break; 60 } 61 } 62 if(col1){ 63 // 判断第 i 行是否只有对角是 1 意思 别人都不认识他,对角是自己认识自己 64 for(int col = 0;col<A.length;col++){ 65 // == 1 说明有人认识他 66 if(col!=i && A[i][col]==1){ 67 row1 = false; 68 break; 69 } 70 } 71 } 72 if(row1 && col1){ 73 count++; 74 res.add(i+1); 75 } 76 } 77 System.out.println(count); 78 for(int i = 0;i<res.size();i++){ 79 System.out.println(res.get(i)); 80 } 81 } 82 83 }
牛客测试内存溢出,给的样例本地测试通过
上面在判断列全是 1 的时候可以对改行的元素求和,和等于人数n的时候符合条件
在判断行只有1的并且是自己认识自己的时候,可以变相的认为和是 0
但是上面还是不能改变定义矩阵的情况
上面可以看到,我们用到的只是矩阵的行的和,和矩阵列的和
定义两个向量来存放行的和和列的和。
定义两个数组:A B
A[i] 表示 i 认识的人数
B[i] 表示 认识 i 的人数
上面去除自己认识自己的情况
当A[i] == 0 B[i] = n-1 的时候 说明这个人不认识别人,却被 n -1个人认识就是答案
题目中说可以有多个,其实最多只有一个,因为这个人要被其余 n -1 个人认识,就不存在两个人的情况了
在牛客不知道为什么下面程序提示“运行错误:请检查是否存在数组越界非法访问,野指针乱访问,空指针乱访问等情况”
1 import java.util.Scanner; 2 3 public class Main { 4 5 /** 6 * 题目: 7 * 找出别人都认识他,而他其他人都不认识的人 8 * 输入: 9 * T T个这样的测试样例 10 * n m n个人 m个关系数 11 * 下面m行就是关系数 12 * 输出: 13 * 第一行:这样的人有几个 14 * 满足条件人的编号 15 * 16 * 若不存在,输出 0 空格 17 */ 18 public static void main(String[] args) { 19 // TODO Auto-generated method stub 20 Scanner scn = new Scanner(System.in); 21 int T = scn.nextInt(); // 测试数据组数 22 while((T--)>0) { 23 int n = scn.nextInt(); // 人数 24 int m = scn.nextInt(); // 关系数 25 if(n == 1){ 26 System.out.print(1+"\n"+1); 27 continue; 28 } 29 if(m<n-1){ 30 System.out.print(0+"\n"+0); 31 continue; 32 } 33 34 // 认识人的数量 35 int[] A = new int[n+1]; 36 // 被认识的数量 37 int[] B = new int[n+1]; 38 // m1 认识 m2 39 for(int k =0;k<m;k++){ 40 int m1 = scn.nextInt(); 41 int m2 = scn.nextInt(); 42 43 if(m1!=m2){ 44 // m1 认识的人数 去除自己的情况 45 A[m1]++; 46 //m2 被多少人认识,去除自己的情况 47 B[m2]++; 48 } 49 } 50 // 自己认识自己的情况可以不用考虑,A[i] = 0 表示 i 不认识除自己以外的其他人, B[i] = n-1 表示i 其他人都认识 51 int id = -1; 52 for(int kk = 1;kk<=n;kk++){ 53 if(A[kk]==0 && B[kk]==n-1){ 54 id = kk; 55 break; 56 } 57 } 58 if(id == -1){ 59 System.out.print("0\n\n"); 60 }else{ 61 System.out.print(1+"\n"+id+"\n"); 62 } 63 64 } 65 } 66 67 68 }
以上是关于2016奇虎360研发工程师内推笔试编程题:找镇长的主要内容,如果未能解决你的问题,请参考以下文章
数据挖掘2022年2023届秋招奇虎360机器学习算法工程师 笔试题