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. CentOS 6.4安装OpenOffice

    终端依次输入: (1)sudo yum install openoffice.org-writer (2) sudo  yum install openoffice.org-calc (3) sudo ...

  2. @Resource注解省略name属性后的行为

    @Resource有一个name属性,该属性值为所要注入的Bean实例的id,类似于<property.../>元素的ref属性,不过在spring中允许省略name属性值,省略后在以下情 ...

  3. java新手笔记22 接口示例2

    1.USB package com.yfs.javase; public interface USB { //定义规范 public void read(); public void write(); ...

  4. java Email发送及中文乱码处理。

    public class mail { private String pop3Server=""; private String smtpServer=""; ...

  5. Codevs 1066 引水入城 2010年NOIP全国联赛提高组

    1066 引水入城 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 在一个遥远的国度 ...

  6. Headfirst设计模式的C++实现——抽象工厂(Abstract Factory)

    Dough.h #ifndef _DOUGH_H #define _DOUGH_H class Dough { }; #endif ThinCrustDough.h #ifndef _THIN_CRU ...

  7. 理解Java中的字符串类型

    1.Java内置对字符串的支持: 所谓的内置支持,即不用像C语言通过char指针实现字符串类型,并且Java的字符串编码是符合Unicode编码标准,这也意味着不用像C++那样通过使用string和w ...

  8. 新开窗口不被拦截的方法-window.open和表单提交form

    $("#btn").click(function() { var w = window.open(); setTimeout(function() { w.location = & ...

  9. 在Apache下开启SSI配置支持include shtml html和快速配置服务器

    作为前端开发,使用Apache快速搭建服务器极为方便. 1.找到apach安装目录,找到conf目录下 的httpd.conf 使用SSI(Server Side Include)的html文件扩展名 ...

  10. "position:relative"在IE中的Bug

    当子元素过高导致父元素出现滚动条时,它并不会像预期的那样呆在父元素里,而是浮在父元素之上,并且位置不随滚动条的移动而改变.根源就是子元素的"position:relative".目 ...