[Locked] Find the Celebrity

Find the Celebrity

Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist one celebrity. The definition of a celebrity is that all the other n - 1 people know him/her but he/she does not know any of them.

Now you want to find out who the celebrity is or verify that there is not one. The only thing you are allowed to do is to ask questions like: "Hi, A. Do you know B?" to get information of whether A knows B. You need to find out the celebrity (or verify there is not one) by asking as few questions as possible (in the asymptotic sense).

You are given a helper function bool knows(a, b) which tells you whether A knows B. Implement a function int findCelebrity(n), your function should minimize the number of calls to knows.

Note: There will be exactly one celebrity if he/she is in the party. Return the celebrity's label if there is a celebrity in the party. If there is no celebrity, return -1.

分析:

  名流的定义竟然是其他所有人都知道他,而他却不知道其他任何人!好吧,承认也差不多是这么回事。言归正传,根据定义,名流首先需要保证所有人都知道他,所以复杂度至少为O(n);暴力解法为两两都问两遍,复杂度为O(n^2)。可以转换下思路,我们可以先去掉所有不可能是名流的人,然后对剩下O(1)个人,进行O(n)复杂度的检验。我想到的其中一个做法是,将n个人分为n/2组,每组两两问一遍,这样一轮就会至少去掉一半的人;然后循环迭代。复杂度为n + n/2 + n/4 +... = 2n。最后最多剩下一个人,进行2(n - 1)次经验。故总复杂度为2n + 2(n - 1) = O(n)。

代码:

int findCelebrity(int n) {
    vector<int> candidate1, candidate2;
    for(int i = 0; i < n; i++)
        candidate1.push_back(i);
    //根据名流的必要性条件,去除所有一定不是名流的人
    while(candidate1.size() > 1) {
        for(int i = 0, j = 1; j < candidate1.size(); i += 2, j += 2) {
            if(knows(i, j) && !knows(j, i))
                candidate2.push_back(j);
            else if(knows(j, i) && !knows(i ,j))
                candidate2.push_back(i);
        }
        vector<int> ().swap(candidate1);
        candidate1.swap(candidate2);
    }
    //直接去除光了,表明无名流
    if(candidate1.empty())
       return -1;
    int candidate = candidate1[0];
    for(int i = 0; i < n; i++)
        //验证充要条件不成立,表明无名流
        if(i != candidate && (!knows(i, candidate) || knows(candidate, i)))
            return -1;
    //满足充要条件
    return candidate;
}

 

posted @ 2016-02-26 14:45  CarlGoodman  阅读(234)  评论(0编辑  收藏  举报