[LeetCode#277] Find the Celebrity
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 - 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
.
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的更多相关文章
- 名人问题 算法解析与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 ...
- [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 ...
- 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 ...
- [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 ...
- [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 ...
- 【LeetCode】277. Find the Celebrity 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力 日期 题目地址:https://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 exi ...
- [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 ...
- LeetCode All in One 题目讲解汇总(持续更新中...)
终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...
随机推荐
- linux下apache-tomcat的安装
一.JDK安装 1.安装JDK软件包 本例使用的JDK安装包为jdk-6u19-linux-x64.bin,该包是一个编译好的二进制可执行程序包,只需要执行即可安装. 首先进入存放JDK安装包的目录( ...
- weewwe
http://blog.csdn.net/u013073524/article/details/25912891
- struts2标签学习笔记(一)
struts2所有标签都定义在一个s标签库里.虽然struts2把所有的标签都定义在URI为"/struts-tags"空间下,但依然可以对struts2标签进行简单的分类. 1. ...
- 加载jar文件输出class和method
package file import java.util.jar.JarEntry import java.util.jar.JarFile import org.junit.Test; class ...
- 无刷新删除 Ajax,JQuery
1.数据库用上面的,增加一个 DeleteById 的SQL方法 delete from T_Posts where Id = @Original_Id 2.设置处理页面 delete.ashx pu ...
- windows下使用xampp一键安装apache+php运行环境
感谢浏览,欢迎交流=.= 想为我老爸开发一套库存管理系统,借此机会打算使用下ext+php+apache+linux环境尝尝鲜. 为了在windows搭建本地开发测试环境,官网下载xampp,一键安装 ...
- ubuntu mint 开机启动项管理
使用工具 sysv-rc-conf,需要安装. 点击打开链接http://blog.chinaunix.net/uid-21516619-id-1825027.html
- hadoop1中partition和combiner作用
---恢复内容开始--- 1.解析Partiton 把map任务的输出的中间结果按照key的范围进行划分成r份,r代表reduce任务的个数.hadoop默认有个类HashPartition实现分区, ...
- python入门 第二天笔记
程序主文件标志if __name__=="__main__": 在程序执行python 1.py 时候 程序1.py __name__ 为 main调用其他文件是,__name__ ...
- GitHub使用教程for Eclipse
1.下载egit插件http://www.eclipse.org/egit/ http://www.eclipse.org/egit/download/ Installing the Latest R ...