名人问题的算法
问题描述:名人问题
一个名人就是指这样一个人:所有其他人都认识他,并且他不认识任何其他人。现在有一个N个人的集合,以及他们之间的认识关系。求一个算法找出其中的名人(如果有的话)或者判断出没有名人(如果没有的话)。
很著名的一道面试题,希望大家一起讨论一下~~
[解决办法]
建立一个图,A认识B就从A到B划道弧,计算每个节点的入度和出度.入度为N出度为0的即可。
时间复杂度O(N^2)
[解决办法]
间一个图。。遍历, O(n^2)出结果。很直接的想法。
[解决办法]
建立一个结构体数组a[N].count初始值为0,,a[i].count表示第i个人被认识的人数..
a[N].count1初始值为0 ,a[i].count1表示第i个人认识的人数
录入数据,如果k认识i 则a[i].count++;a[k].count1++
录完数据后,遍历数组,如果 a[i].count=N-1 且a[i].count1=0;则是名人
[解决办法]
可以构建一个矩阵,A[N][N],N是人的个数。
初始化时A[N][N]的值全为0;
每读入一认识关系时,如i认识k,则A[i][k]赋为1;
最后,如果对于一个特定的m,有矩阵A第m行全为0,而第m列全为1,则m为名人。
[解决办法]
这个问题还可以优化
因为如果存在名人,那按定义只可能有一个
剩下的计算,如LS说的,建个有向图
第一次遍历找出是否只存在一个节点,出度为0,如果存在这样的节点,说明可能存在名人,如果不存在,那肯定不存在名人,直接返回就可以
第一次遍历,判断除第一步找的出度为0的点之外,其它的节点是否都存在一条指向出度为0节点的边,如果其它节点都满足,则说明出度为0的点就是名人,否则不存在名人
[解决办法]
只是处理输入,就需要O(E)的时间,其中E是边的数量。
如果有了数据,应该O(n)就可以统计出谁是名人(根据入度和出度),不用n*log(n),
如果用随机化的方法,应该可以以低于O(n)的时间找到名人,
其方法就是类似DFS,随机找到一个人,如果此人是名人,return,如果不是,对此人做标记,
从此人认识的人里随机找1个,如此迭代,应该比逐个判断效率要高一些,但具体平均复杂度是多少,不太好算。