Leetcode - 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 - 1people 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.

[分析]

思路1:暴力法,检查每个人是否满足celebrity的性质。

思路2:参考https://leetcode.com/discuss/56350/straight-forward-c-solution-with-explaination

遍历数组两次,第一次遍历找到第一个也是最后一个后面元素都认识的candidate, 第二次遍历确认前面元素都认识这个candidate并且candidate不认识其他任何一个人。

特别注意第一次遍历的思路。

讨论区另一个类似思路:https://leetcode.com/discuss/56413/java-solution-two-pass 是有bug的,这个思路第一次遍历是检查candidate是否认识当前元素,

假设0号宾客谁也不认识,则它会被误认为是celebrity而找不出真正的celebrity。

选出celebrity的候选者关键是要找出ta 同其他宾客的区分点:只有他是全部人都认识的, 而他不认识其他任何宾客这个条件不能作为区分点。

/* 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 cand = 0;
        for (int i = 1; i < n; i++) {
            if (!knows(i, cand))
                cand = i;
        }
        for (int i = 0; i < n; i++) {
            if (i != cand && (knows(cand, i) || !knows(i, cand)))
                return -1;
        }
        return cand;
    }
    public int findCelebrity1(int n) {
        int[] beknown = new int[n];
        boolean[] knowSb = new boolean[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (j == i) continue;
                if (knows(i, j)) {
                    beknown[j]++;
                    knowSb[i] = true;
                }
            }
        }
        for (int i = 0; i < n; i++) {
            if (beknown[i] == n - 1 && !knowSb[i])
                return i;
        }
        return -1;
    }
}

 

posted @ 2015-09-13 20:42  abcxyz00  阅读(351)  评论(0编辑  收藏  举报