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. tableview刷新某个区域(section)或者某一行(row)

    //一个section刷新 NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:2]; [tableview reloadSections:in ...

  2. 在Windows下用gSoap实现简单加法实例

    实现一个简单的a+b程序,在服务器端写一个程序,里面包含了a+b的函数,然后通过客户端代码向其发送两个数字,在服务器运算得到结果返回给客户端显示出来. 1.在gSoap的官网上下载文件夹,本人的版本是 ...

  3. C#控件命名规范

    文档名称: C#控件命名规范 撰写作者: codefly 版本编号: V1.1 C#控件命名规范 一.Data Control 类型 前缀 示例 AccessDataSource ads adsPub ...

  4. rsync 的使用和参数解释

    备份往往可以为我们提供一种恢复的策略,因此在实际的生产应用中我们需要对系统的各个配置以及数据进行备份.然而普通的备份都是在本地磁盘或者相应的设备上进行,其实这样也存在一种缺陷,就是设备也出现问题怎么办 ...

  5. ubuntu基本操作(2)

    查看当前使用那种 shell echo $SHELL 更换 shell 类型:首先检查是否安装了相应的类型 shell开启终端,直接输入相应的 shell 名称如果没有安装,则先安装,否则直接启动此时 ...

  6. .NET异步操作学习之一:Async/Await中异常的处理

    以前的异常处理,习惯了过程式的把出现的异常全部捕捉一遍,然后再进行处理.Async/Await关键字出来之后的确简化了异步编程,但也带来了一些问题.接下来自己将对这对关键字进行学习.然后把研究结果放在 ...

  7. [C#]『CountdownEvent』任务并行库使用小计

    System.Threading.CountdownEvent  是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定. CountdownEvent  专门用于以下情况:您必须使用 ...

  8. $_REQUEST变量数组header()函数

    $_SERVER 包含http信息头,路径和服务器端的一些信息,没发送一次HTTP请求,就会创建一个$_SERVER数组Array ( [HTTP_HOST] => localhost [HTT ...

  9. 全面理解.htaccess语法中RewriteCond和RewriteRule意义

    RewriteCond的语法 RewriteCond TestString CondPattern [Flags]其中的TestString是指一个文本格式的条件,例子中用的是环境变量名HTTP_HO ...

  10. 斗地主你什么时候才会托管?(.NET中的托管于非托管)

    文章部分引自<.NET4.0面向对象编程漫谈(基础篇)>第1章.NET面向对象编程基础(作者:金旭亮) 无意间看到一位四五岁左右小朋友在玩斗地主,总开始到结束,她一直都在使用“提示”(托管 ...