Among n
persons,a "celebrity" is defined as someone
who is known by everyone but does not know anyone. The
problem is to identify the celebrity, if one exists, by asking the
question only of the form, "Excuse me, do you know the person
over there?" (The assumption is that all the answers are correct,
and even that celebrity will also answer.)
The goal is to minimize the number of questions.
Is there a solution of the order less than the obvious O(n^2)
here?
答案 0 :(得分:10)
使用名人问题的分析here
暴力解决方案。图表最多有
n(n-1)
个边缘,我们可以通过询问每个潜在边缘的问题来计算它。在这 我们可以通过计算它来检查顶点是否是一个接收器 indegree及其outdegree。这个暴力解决方案要求n(n-1)
的问题。接下来,我们将展示如何使用3(n-1)
进行此操作 问题和线性的地方。优雅的解决方案。我们的算法包含两个阶段:在淘汰阶段,我们消除除了一个人以外的所有人 名人;在验证阶段,我们检查是否这一个 剩下的人确实是个名人。消除阶段 维护可能的名人名单。最初它包含所有
n
人。在每次迭代中,我们从列表中删除一个人。我们 利用以下关键观察:如果人1
知道人2
, 那么人1
不是名人;如果某人1
不认识某人2
, 那么人2
不是名人。因此,通过询问人1
他是否知道 在2
人,我们可以从列表中删除任何人1
或人2
可能的名人。我们可以反复使用这个想法来消除 一个人p
,除了一个人之外的所有人。我们现在通过蛮力验证p
是否为名人:对于其他所有人i
,我们会问p
他是否认识某人i
,并询问他们i
他们是否知道 人p
。如果人p
总是回答否,而其他人总是回答 回答是的,我们宣布人p
为名人。否则,我们 得出结论,这个群体中没有名人。
答案 1 :(得分:8)
将所有人分开。
对于每一对(A,B),如果他知道B,请询问A.
现在,只剩下一半人。
从1开始重复,直到只剩下一个人。
成本O(N)。
答案 2 :(得分:5)
可以使用 O(N ^ 2)时间复杂度的图(度数和度数概念)解决该问题。
我们还可以使用简单的两指针概念在 O(N)时间和O(1)空间中解决此问题。 我们将一次比较两个人,一个人从头开始,另一个人从末尾比较,我们将把这个人从不能成为名人的考虑中剔除。例如,如果有两个人X,而Y和X可以识别人Y,则X肯定是名人,因为它认识此党内的一个人。另一种情况是X不认识Y,并且在这种情况下,Y不能成为名人,因为在聚会中至少有一个不认识他/她的人。利用这种直觉,两指针概念可以应用于在这个聚会中寻找名人。
我在算法上找到了一个关于YouTube的很好的解释性视频。
您可以参考此视频以获得更好的解释。
视频链接:
答案 3 :(得分:2)
这是O(N)时间算法
答案 4 :(得分:0)
这是我的解决方案。
#include<iostream>
using namespace std;
int main(){
int n;
//number of celebrities
cin>>n;
int a[n][n];
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cin>>a[i][j];
}
}
int count = 0;
for(int i = 0;i < n;i++){
int pos = 0;
for(int j = 0;j < n;j++){
if(a[i][j] == 0){
count = count + 1;
}
else{
count = 0;
break;
}
}
if(count == n){
pos = i;
cout<<pos;
break;
}
}
return 0;
}
答案 5 :(得分:0)
这就是我做的方式:)
问题 - 名人被定义为其他人都知道的人,但不认识任何人。给定N个人(索引0 ...(N-1)),并且函数knownOf定义 如下:knowsOf(int person0,int person1)=如果人0知道人1则为真,否则为假 找出N人中的名人,如果有的话。
//如果没有名人则返回-1,否则返回人员索引/编号。
public int celeb(int n) {
int probaleCeleb = 0;
for(int i =1 ; i < n; i++) {
if(knowsOf(probaleCeleb , i)) { // true /false
probaleCeleb = i;
}
}
for(int i =0 ; i < n; i++) {
if( i != probaleCeleb &&
(!knowsOf( i , probaleCeleb) || (knowsOf( probaleCeleb , i)) ) {
probaleCeleb = -1;
break;
}
}
return probaleCeleb;
}
}
答案 6 :(得分:0)
public class Solution {
public int findCelebrity(int n) {
if (n <= 1) {
return -1;
}
int left = 0;
int right = n - 1;
// First find the right candidate known by everyone, but doesn't know anyone.
while (left < right) {
if (knows(left, right)) {
left++;
} else {
right--;
}
}
// Validate if the candidate knows none and everyone knows him.
int candidate = right;
for (int i = 0; i < n; i++) {
if (i != candidate && (!knows(i, candidate) || knows(candidate, i))) {
return -1;
}
}
return candidate;
}
}
答案 7 :(得分:0)
int findCelebrity(int n) {
int i=0;
for(int j=1;j<n;j++){
if(knows(i,j)){
i=j;
}
}
for(int j=0;j<n;j++){
if(j!=i && (knows(i,j)|| !knows(j,i))){
return -1;
}
}
return i;
}