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。你能否像桂一样快速找到合适的镇长人选呢? 
输入描述:
首先一个正整数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机器学习算法工程师 笔试题

数据挖掘2022年2023届秋招奇虎360机器学习算法工程师 笔试题

奇虎360 技术岗A编程题 -- 内存管理

链家秋招内推编程笔试题目

2021贝壳找房春招C++工程师笔试卷2

360笔试编程题