#leetcoce#277. Find the Celebrity

来源:互联网 发布:淘宝上依伊芭莎女模特 编辑:程序博客网 时间:2024/05/18 02:48

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.

--------------------------------------------------------------------------------------------------------------------

由题目秒数得知,celebrity如下性质: 

  1. 其他所有人都认识 celebrity, 如下图 蓝色的 T, 表示 true
  2. celebrity 不认识其他所有人, 如下图红色的 F, 表示 false

题目给的 knows(a, b) 如果返回 true,则 a 认识 b, a 不可能是 celebrity, 

如果返回 false,则 a 不认识 b, b 不可能是 celebrity, 所以每call 一次 knows()method,总能排除一个人,

最开始想的两层循环,根据上面的性质一一排除,到最后剩一个的时候再按照celebrity的性质判断是否符合


两两比较更有效率, 维护一个Queue,把有可能的人放在queue中比较,最后剩一个的时候就是可能的celebrity。用了一个Boolean[][] 数组来避免重复的 knows() call

 012340FTTTF1FFTTT2FFFTT3FFFFF4TTTTF

/* The knows API is defined in the parent class Relation.      boolean knows(int a, int b); */public class Solution extends Relation {    public int findCelebrity(int n) {        Queue<Integer> queue = new LinkedList<>();        for(int i = 0; i < n; i++){            queue.offer(i);        }        Boolean[][] know = new Boolean[n][n];//default will be null        while(!queue.isEmpty()){            if(queue.size() == 1){                //now there is only one people that might be the celebrity, we need to iterate all other people to see if this guy satisfies he/she does not know any others && all others knows him/her                int cur = queue.poll();                for(int i = 0; i < n; i++){                    if(i == cur)                        continue;                    if(know[cur][i] == null){                        if(knows(cur, i)){                            return -1;                        }                    }else if(know[cur][i]){                        return -1;                    }                                                            if(know[i][cur] == null){                        if(!knows(i, cur)){                            return -1;                        }                    }else if(!know[i][cur]){                        return -1;                    }                }                return cur;            }            int i = queue.poll();            int j = queue.poll();            if(knows(i, j)){//i knows j, i must not be the celebrity, j may be                queue.offer(j);                know[i][j] = true;            }else{//i does not know j, j must not be the celebrity, i may be                queue.offer(i);                know[i][j] = false;            }        }                return -1;    }}



看了discuss的讨论,发现下面的解法更简洁一些,调用 knows 的次数肯定比维护 Boolean[][]数组多,但是多得也比较有限。

因为每次调用 knows() , 都可以排除掉一个人,所以下面这种方法和维护Queue然后一直比较 有可能成为 celebrity的人的比较次数是同样的,都是 n - 1 次 比较。


/* The knows API is defined in the parent class Relation.      boolean knows(int a, int b); */public class Solution extends Relation {    public int findCelebrity(int n) {        int candidate = 0;        for(int i = 1; i < n; i++){            if(knows(candidate, i)){                candidate = i;            }        }        // now we already know that for x in [candidate + 1 to n - 1], knows(candidate, x) returns false;        for(int i = 0; i < n; i++){            if(i == candidate){                continue;            }            if(i < candidate && knows(candidate, i)){                return -1;            }            if(!knows(i, candidate)){                return -1;            }        }        return candidate;    }        }



原创粉丝点击