360 内推笔试 - 挑选镇长

试题来源:http://www.nowcoder.com/question/next?pid=151724&qid=25196&tid=718946

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≤10^5 ,0≤m≤3×10^5 ),依次表示镇上的人数和相互之间的认识关系数。

之后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



解析:

思路一

用一个 n*n 二维数组 表示人与人之间的认识关系,

1 认识 2 则 Know[1][2] = true; 否则 Know[1][2] = false;

那么满足镇长条件的 j 号村民 ,1~n 号全认识 j 号 村民,即 Know 数组中Know[1~n][j] 全为true,且 j 号村民不认识除自己外的村民,即 Know[j][1~n] 全为 false

时间复杂度O(n^2), 空间复杂度O(n^2)

提交后,内存不符号要求。

思路二

既然O(n^2)的内存不满足要求,那能不能,用O(n)来表示相互的认识关系。

采用投票的思路:如果 A 认识 B 则 A 投出一票, B 得到一票,不能投票给自己。

如果 n 个村民,其中一个村民得到了 n-1 票,投出了 0 票,那么他是个候选人。

只需用 2 个 一维数组记录投票结果,空间复杂度O(n),时间复杂度O(n)

提交结果:AC

经验教训:考试时没能做出来,一是因为时间问题,二是不够冷静,不能静下来仔细分析问题。

题目不是难,而是没用心。

思路一 源码实现:

#include <iostream>
#include <vector>
using namespace  std;
int main()
{
    int T;
    cin >> T;
    int n, m;
    vector<int> *mayor = new vector<int>[T];
    int k = 0;
    while (k < T && cin >> n >> m) {
        bool** know = new bool*[n+1];
        for (int i = 0; i < n+1; i++)
            know[i] = new bool [n+1];
        for (int i = 1; i < n+1; i++) {
            for (int j = 1; j < n+1; j++) {
                    know[i][j] = (i == j) ? true : false;
            }
        }
        int A, B;
        // 输入 m 组关系数
        for (int i = 0; i < m; i++) {
            cin >> A >> B;
            know[A][B] = true;
        }
        for (int j= 1; j < n+1; j++) {
            bool all_know_j = true;
            for (int i = 1; i < n+1; i++) {
                all_know_j = all_know_j && know[i][j]; // 判断是否所有人都认识 j
            }
            if (all_know_j == true) {
                bool j_know_person = false;
                for (int p = 1; p < n+1; p++) {
                    if (j == p)
                        continue; // 跳过自己
                    j_know_person = j_know_person || know[j][p]; // 判断 j 是否不认识所有人
                }
                if (j_know_person == false) {
                    mayor[k].push_back(j);
                }
            }
        }
        for (int i = 0; i < n+1; i++) {
            delete []know[i];
        }
        delete []know;
        know = NULL;
        k++;
    }
    for (int i = 0; i < T; i++) {
        cout << mayor[i].size() << endl;
        for (int j = 0; j < mayor[i].size(); j++) {
            cout << mayor[i][j] << " ";
        }
        cout << endl;
    }
}

思路二源码实现:

#include <iostream>
#include <vector>
using namespace  std;
int main()
{
    int T;
    cin >> T;
    int n, m;
    vector<int> *mayor = new vector<int>[T];
    int k = 0;
    while (k < T && cin >> n >> m) {
        unsigned int* elected = new unsigned int [n+1]; // 被投票的次数
        unsigned int* elect = new unsigned int [n+1]; // 投票的次数
        for (int i = 0; i < n+1; i++) {
            elected[i] = 0;
            elect[i] = 0;
        }
        int A, B;
        // 输入 m 组关系数
        for (int i = 0; i < m; i++) {
            cin >> A >> B;
            if (A != B) {
                elected[B]++; // A 认识 B,B被投一票
                elect[A]++; // A 投出一票
            }
        }
        for (int i = 1; i < n+1; i++) {
            if (elected[i] == n-1 && elect[i] == 0)
                mayor[k].push_back(i); // 得到 n-1 个选票,投出 0 票的人是镇长人选
        }
        delete []elected;
        delete []elect;
        k++;
    }

    for (int i = 0; i < T; i++) {
        cout << mayor[i].size() << endl;
        for (int j = 0; j < mayor[i].size(); j++) {
            if (j > 0)
                cout << " ";
            cout << mayor[i][j];
        }
        cout << endl;
    }
    delete []mayor;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 13:51:46

360 内推笔试 - 挑选镇长的相关文章

2016奇虎360研发工程师内推笔试编程题:找镇长

挑选镇长 360员工桂最近申请了一个长假,一个人背着包出去自助游了. 路上,他经过了一个小镇,发现小镇的人们都围在一棵树下争吵.桂上前询问情况,得知小镇的人们正缺一个镇长,他们希望能选一个知名又公正的镇长,即,大家希望能选出一个人,所有人都认识他,但同时他不认识镇上除自己以外的其他人(在此,我们默认每个人自己认识自己).可是小镇里的人太多了,一下子大家谁也说服不了谁. “这简单啊.”桂表示.于是他一下子统计出来了镇上人们相互之间的认识关系,并且一下子找到了合适的镇长人选. 现在你手上也拿到了这样

WYYD2017内推笔试回顾

这次内推的笔试考试感觉就是挺杂的,考题没有区分大的方向.ios和研发工程师的题目没区别.编程题也是一样,就是顺序换了下,所以编程题也没有难度梯度的区分,有些不科学.扯这么多其实感觉还是自己的基础不扎实,得加油了. 下面回忆一下考到了什么. 选择题(单选和多选,2分×15题=30分) 这边只能大致回忆起一些知识点了 1.Linux下管道命令来统计for循环的次数会用到哪些指令? (多选)选项: cat.wc.grep.vi 2.解释和编译的比较,效率,是否生成本地文件,是否独立于机器等 3.B-数

网易2017校招内推笔试练习卷编程题1--1019.数字黑洞20

给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到 一个新的数字.一直重复这样做,我们很快会停在有"数字黑洞"之称的6174,这个神奇的数字也叫Kaprekar常数. 例如,我们从6767开始,将得到 7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174 7641 - 1467 = 6174 ... ... 现给

网易2017校招内推笔试练习卷编程题2--出专辑

你作为一名出道的歌手终于要出自己的第一份专辑了,你计划收录 n 首歌而且每首歌的长度都是 s 秒,每首歌必须完整地收录于一张 CD 当中.每张 CD 的容量长度都是 L 秒,而且你至少得保证同一张 CD 内相邻两首歌中间至少要隔 1 秒.为了辟邪,你决定任意一张 CD 内的歌数不能被 13 这个数字整除,那么请问你出这张专辑至少需要多少张 CD ? 输入描述: 每组测试用例仅包含一组数据,每组数据第一行为三个正整数 n, s, L. 保证 n ≤ 100 , s ≤ L ≤ 10000 输出描述

360编程题:挑选镇长

#include<iostream> using namespace std; typedef struct Relation_ { int first; int end; }Re; typedef struct Leader_ { int mun; int*pResult; }Le; Le GetLeader(int Sum,int M,Re*pRelation) { int i=0; int*p1=new int [Sum];//biao shi zong ren ren shi de r

58前端内推笔试2017(含答案)

1.填空题 (1)获取随机数的方法:Math.random (2)JS中奖一个变量前置强制改成浮点类型的方法:parseFloat(String) (3)根据id获取元素的原生js方法:getElementById(); (4)将文档声明为HTML5文档类型,需要在文档头添加:<!DOCTYPE html> (5)Chrome浏览器的私有样式前缀:-webkit- (6)CSS3设置圆角的属性名:border-radius (7)CSS中,#是根据id来选择元素的,.是根据类名来选择元素的.

2017 网易有道研发内推笔试编程题 8.17

15个选择题,每个2分,3个程序题,每个30.

[遇见时光]内推笔试-藏宝图-java实现

牛牛拿到了一个藏宝图,顺着藏宝图的指示,牛牛发现了一个藏宝盒,藏宝盒上有一个机关,机关每次会显示两个字符串 s 和 t,根据古老的传说,牛牛需要每次都回答 t 是否是 s 的子序列.注意,子序列不要求在原字符串中是连续的,例如串 abc,它的子序列就有 {空串, a, b, c, ab, ac, bc, abc} 8 种. 输入描述: 每个输入包含一个测试用例.每个测试用例包含两行长度不超过 10 的不包含空格的可见 ASCII 字符串. 输出描述: 输出一行 “Yes” 或者 “No” 表示结

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

参加8.19的链家内推笔试,总体来说题目难度不大,20个选择题还有三道编程题. 选择题,里面有两道关于IP地址计算的题目,有点忘了,不知道最后的计算有没有问题,所以还需要复习学习完的知识, 因为不知道什么时候就会遇到相关的问题. 编程题,自我感觉,难度是偏简单的,如果不能达到两道AC,那就是不合格了. 1. 给定的一个1,2,3组成的数字序列,排成升序所需的最少交换次数 . 样例输入: 9 2 2 1 3 3 3 2 3 1 样例输出: 4 思路: 应使用贪心算法. 分析:先存入数组,然后记录有