用于寻找名人群的线性算法,而非单一名人

时间:2014-01-07 22:26:35

标签: algorithm

假设我们有N个人,那里可能是一群名人。

每个人都知道每个名人,每个名人都只知道其他所有名人。

如果您获得了know x y returns true or false的功能,请确定名人群。

这个问题是识别一群名人,并且没有识别人中唯一的名人,例如http://www.geeksforgeeks.org/the-celebrity-problem/


使用蛮力很容易。我可以构建N个人的所有可能的子序列并用条件过滤它们(每个人都知道每个名人,每个名人都只知道其他名人)。

我也知道必须只有一个名人组或没有。

证明:

假设我们有两个名人组,C1和C2。因为每个人都知道来自C1的ci,所以来自C2的每个cj也知道ci;对称地,每个ci都知道cj;所以C1和C2实际上属于一个组。所以我们最多只有一个名人组或没有。

关于可能的线性算法的任何想法?

修改

可能有一群名人,可能没有。

5 个答案:

答案 0 :(得分:8)

是的,这可以在O(N)中进行(但请参见下面的第2次编辑)。这是一种算法。

列举从0到N-1的所有N个人。

int find_a_celebrity()
{
    int C = 0; // C is a potential celebrity
    for( int i=0 ; i<N ; ++i )
      if( !know(i,C) ) // C is not a celebrity nor are all j<i, but i might be.
        C = i; 
    for( int i=0 ; i<N ; ++i ) // Loop a second time to check everyone knows C.
      if( !know(i,C) ) return -1;
    return C;
}
int C = find_a_celebrity();

如果C==-1那么就没有名人了。否则,集合{ y | know(C,y) }是所有名人的集合。总而言之,所有N人最多需要3次迭代,因此可以及时发现O(N)

编辑:

// Output the set of celebrities
if( C == -1 ) std::cout << "There are no celebrities.";
else for( int i=0 ; i<N ; ++i ) if( know(C,i) ) std::cout << i << ' ';
std::cout << std::endl;

编辑2:

这个问题有两种解释:

  1. 名人的定义是每个人都知道。由于问题的限制,所有名人只知道其他名人。
  2. 名人的定义是每个人都知道,名人只知道其他名人。
  3. 上述算法针对情况#1解决了这个问题。这适用于案例#2,只要我们可以假设存在至少一个名人。否则,我们必须在最后确认潜在名人的名单只相互了解,这需要O(N*M)时间,其中M是潜在名人的数量。

答案 1 :(得分:0)

编辑:我没有仔细阅读问题陈述。您没有所有边的列表,我们假设我们无法在线性时间内生成它。

这里的关键是每个人都知道每个名人。将此问题表示为有向邻接图,其中V顶点(名人)和E边(关系)连接它们。

通过列表E迭代计算每个人的知晓次数。名人被称为V-1次;其他人都是非名人。运行时间应为O(E)。

答案 2 :(得分:0)

作为一个名人是在不知情的情况下被人知道的状态。正常是知道的状态而不为人所知。因此,将每个人与他们旁边的人进行比较看起来像是:

foreach person in persons
{
  knows = know(person, next_person)
  isknown = know(next_person, person)

  if knows and !isknown then normal
  if !knows and isknown then celeb
  if !knows and !isknown then normal
  if knows and isknown then friends.add(person)

  foreach friend in friends
  {
      alsoknows = know(person, friend)
      if !alsoknows then normal; break;
  }
}

答案 3 :(得分:0)

考虑所有N *(N-1)个可能的know(x,y)评估为真的情况。在这种情况下,所有N人都是名人。接下来,考虑除了知道(x,y)的N *(N-1)个评估之一之外的所有情况都是真的情况。根据{{​​3}},我希望我们应该将这种情况解释为没有名人。为了区分这两种情况,您需要评估所有可能的N *(N-1)对。

答案 4 :(得分:-1)

candidates成为所有n人的列表。构建所有人的循环:

1 -> 2 -> ... -> n -> 1

现在,逐一检查knows k,k+1。如果为真,则为k = k+1并继续。如果knows k,k+1 == False,则k+1不是名人,请将其从candidates移除,然后再点击k,k+2

当我们在最后size(candidates)轮次中没有删除任何人时,我们就完成了。

<强>证明:

如果名单中有名人,那么:

  1. 他永远不会被删除
  2. 一旦我们与他联系,我们会进一步向最后一位名人
  3. 算法将删除所有非名人'在最后一个之后',直到我们得到另一个名人,然后我们回到2。
  4. 最后,我们将得到一个名人的循环。

    如果列表中没有名人,请按照@Matt的回答。