Problem:

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.

Analysis:

Even though the problem is not hard, the efficiency could vary a lot, and the concisness of the code could also vary a lot!!!
I have explored following mistakes and implementation until I reach the final solution. Mistake 1:
Put return in "if-else". Note this is a very common mistake, you should always guanratee a default return at last. if (candidates.size() != 1) {
return -1;
} else{
for (int i : candidates)
return i;
} Line 27: error: missing return statement Mistake 2: Modify sets when iterate on it.
public class Solution extends Relation {
public int findCelebrity(int n) {
if (n <= 0)
throw new IllegalArgumentException("n is invalid");
HashSet<Integer> candidates = new HashSet<Integer> ();
for (int i = 0; i < n; i++)
candidates.add(i);
for (int i = 0; i < n; i++) {
for (int j : candidates) {
if (i != j) {
if (knows(i, j))
candidates.remove(i);
else
candidates.remove(j);
}
}
}
if (candidates.size() == 1) {
for (int i : candidates)
return i;
}
return -1;
}
} Runtime Error Message:
Line 26: java.util.ConcurrentModificationException Note: this is absolutely allowed!!! A way to avoid this is to use a HashSet to record all the elements you want to remove. When you finish the iteration, then you can remove those elements through "set.removeAll()" method to remove them. public class Solution extends Relation {
public int findCelebrity(int n) {
if (n <= 0)
throw new IllegalArgumentException("n is invalid");
HashSet<Integer> candidates = new HashSet<Integer> ();
HashSet<Integer> excludes = new HashSet<Integer> ();
for (int i = 0; i < n; i++)
candidates.add(i);
for (int i = 0; i < n; i++) {
for (int j : candidates) {
if (i != j) {
if (knows(i, j)) {
excludes.add(i);
} else{
excludes.add(j);
}
}
}
candidates.removeAll(excludes);
}
if (candidates.size() == 1) {
for (int i : candidates)
return i;
}
return -1;
}
} Input:
0 knows 1; 1 knows 0.
Output:
1
Expected:
-1 As you can see from the error notification, the above solution could still be wrong. The problem is that even there maybe only "1 element" left in the candidates set, it may not be the answer. case 1: iff such celebrity exist, there must one element left.
case 2: iff not exist, there also could be elements left in the Set, thus we have to do the final check to resure the left element is a celebrity/ Update:
public class Solution extends Relation {
public int findCelebrity(int n) {
if (n <= 0)
throw new IllegalArgumentException("n is invalid");
HashSet<Integer> candidates = new HashSet<Integer> ();
HashSet<Integer> excludes = new HashSet<Integer> ();
for (int i = 0; i < n; i++)
candidates.add(i);
for (int i = 0; i < n; i++) {
for (int j : candidates) {
if (i != j) {
if (knows(i, j)) {
excludes.add(i);
} else{
excludes.add(j);
}
}
}
candidates.removeAll(excludes);
}
for (int i : candidates) {
for (int j = 0; j < n; j++) {
if (i != j) {
if (knows(i, j) || !knows(j, i))
return -1;
}
}
}
for (int i : candidates)
return i;
return -1;
}
} We have used two HashSets in the above solution, and for each non-repeative comparision, we could eliminate one candidate out. Thus for the above code the time complexity is actually O(n). Actually, using above conclusion, we could write the code into a more elegant way. We could use a stack to guarantee:
1. if there is a celebrity, it must remain in the stack(as long as there is an element)
2. there is no repeatitive comparision among candidate. We know for each comparision, we must be able to eliminate one element out.
1. iff A knows B, A must not the celebrity, since celebrity knows no one.
2. iff A did not know B, B must not the celebrity, since everyone knows celebrity. while (stack.size() > 1) {
int i = stack.pop();
int j = stack.pop();
if (knows(i, j))
stack.push(j);
else
stack.push(i);
}
}

Solution:

public class Solution extends Relation {
public int findCelebrity(int n) {
if (n <= 0)
throw new IllegalArgumentException("n is invalid");
if (n == 1)
return 0;
Stack<Integer> stack = new Stack<Integer> ();
for (int i = 0; i < n; i++)
stack.push(i);
while (stack.size() > 1) {
int i = stack.pop();
int j = stack.pop();
if (knows(i, j))
stack.push(j);
else
stack.push(i);
}
int j = stack.pop();
for (int i = 0; i < n; i++) {
if (i != j) {
if (!knows(i, j) || knows(j, i))
return -1;
}
}
return j;
}
}

[LeetCode#277] Find the Celebrity的更多相关文章

  1. 名人问题 算法解析与Python 实现 O(n) 复杂度 (以Leetcode 277. Find the Celebrity为例)

    1. 题目描述 Problem Description Leetcode 277. Find the Celebrity Suppose you are at a party with n peopl ...

  2. [LeetCode] 277. Find the Celebrity 寻找名人

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

  3. LeetCode 277. Find the Celebrity (找到明星)$

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

  4. [leetcode]277. Find the Celebrity 找名人

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

  5. [leetcode]277. Find the Celebrity谁是名人

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

  6. 【LeetCode】277. Find the Celebrity 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力 日期 题目地址:https://leetcode ...

  7. 277. Find the Celebrity

    题目: Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exi ...

  8. [LC] 277. Find the Celebrity

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

  9. LeetCode All in One 题目讲解汇总(持续更新中...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...

随机推荐

  1. 20151223jquery学习笔记--Ajax表单提交

    传统的表单提交, 需要多次跳转页面, 极大的消耗资源也缺乏良好的用户体验. 而这款form.js 表单的 Ajax 提交插件将解决这个问题.一. 核心方法官方网站: http://malsup.com ...

  2. javascript 之封装技巧

    技术--- 闭包 javascript中的对象属性都是公开的,外界都可访问到,例: function cat(){ this.name = '猫'; this.climb = function(){ ...

  3. 控制器的跳转-modal与push

    一.modal与pushmodal从下面往上盖住原来的控制器,一般上一个控制器和下一个控制器没有什么关联时用modal,比如联系人的加号跳转页面,任何控制器都可以用modal push一般是上下文有关 ...

  4. IF EXIST: The syntax of the command is incorrect.

    Batch 脚本中使用 IF EXIST 语句时,总是提示 The syntax of the command is incorrect. 原始 bat 脚本如下: ECHO OFF SET proj ...

  5. Hack--兼容性测试

    CSS hack由于不同的浏览器,比如Internet Explorer 6,Internet Explorer 7,Mozilla Firefox等,对CSS的解析认识不一样,因此会导致生成的页面效 ...

  6. Check Mysql Database Size

    SELECT ROUND( SUM(data_length + index_length) / 1024 / 1024 ) TOTAL_MB, ROUND(SUM(data_length) / 102 ...

  7. 用 Python写 daemon

    转自 http://chowroc.blogspot.com/2007/05/python-how-to-write-daemon.html 最近用 Python 可能要写 daemon,找资料先看看 ...

  8. fork();

    僵死进程: 父进程没有等待子进程,wait() 子进程会变成僵死进程. int main(int arg, char *args[]){ pid_t pid = fork();//调用fork产生一个 ...

  9. linux 文件操作编程

    Linux中所有的设备和文件的操作都使用文件描述符来进行. 文件描述符是一个非负的整数,它是一个索引值,指向内核中每个进程打开的记录表. 当打开一个文件或者创建一个新文件时,内核就向进程返回一个文件描 ...

  10. java中运算符——进度1

    Class Demo1{    public static void main(String[] args) {        /*        一.逻辑运算法用于连接两个boolean类型的表达式 ...