【Leetcode刷题】277. Find the Celebrity 搜寻名人
Link: leetcode277
(English version, 中文站需会员)
问题描述
相关Topics: Array, 贪心算法
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 about 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). 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.
假设你和n个人(从0到n-1进行标注)在一个聚会上,这个聚会里可能存在一个名人。名人的定义是,其余n-1个人都认识他,但是他不认识任何人。
你希望找到谁是名人,或者证明这里不存在名人。你只能通过问问题的方式来得到信息,比如询问 “A,你认识B吗?” 来得到关于A是否认识B的信息,你要尽可能少的询问问题来找到正确答案。
给定一个bool的函数 knows(a, b) 来告诉你A是否认识B,实现int的函数findCelebrity(n),返回名人的标签(至多只有一个名人存在),如果没有名人的话,返回-1。
例子1
输入: graph = [[1,1,0],[0,1,0],[1,1,1]]
输出: 1
解释: 一共有三个人,0号和2号都认识1号,但是1号不认识他们,所以1号是名人,返回1。
例子2
输入: graph = [[1,0,1],[1,1,0],[0,1,1]]
输出: -1
解释: 不存在名人,返回-1。
约束条件:
n == graph.length
n == graph[i].length
2 <= n <= 100
graph[i][j] is 0 or 1.
graph[i][i] == 1
解法1 Brute Force 暴力法
定义函数 is_celebrity(i) 来判断 i 是否为名人,遍历剩下的 n-1 个人,如果剩下的人都认识 i,且 i 不认识剩下的人,那么 i 为名人。
对于聚会里的 n 个人,遍历使用函数 is_celebrity(i) 来寻找名人。
时间复杂度 O(n^2)
空间复杂度 O(1)
class Solution:
def findCelebrity(self, n: int) -> int:
self.n = n
for i in range(n):
if self.is_celebrity(i):
return i
return -1
def is_celebrity(self, i):
for j in range(self.n):
if i == j: continue # Don't ask if they know themselves.
if knows(i, j) or not knows(j, i):
return False
return True
解法2 Logical Deduction 逻辑推理法
如果 knows(A, B) = 1, 即 A 认识 B,那么A一定不是名人,B有可能是名人。
如果 knows(A, B) = 0, 即 A 不认识 B,那么A有可能是名人,B一定不是名人。
下图里,绿线表示认识,红线表示不认识。
我们从0号出发,假定名人 candidate = 0
knows(0, 1) = 0,0号不认识1号,candidate = 0 不变,1号被排除
knows(0, 2) = 1,0号认识2号,candidate = 2,0号被排除
knows(2, 3) = 0,2号不认识3号,candidate = 2 不变,3号被排除
knows(2, 4) = 1,2号认识4号,candidate = 4,2号被排除
knows(4, 5) = 0,4号不认识5号,candidate = 4 不变,5号被排除
knows(4, 6) = 0,4号不认识6号,candidate = 4 不变,6号被排除
knows(4, 7) = 0,4号不认识7号,candidate = 4 不变,7号被排除
那么现在可能为名人的只有4号,于是我们调用 is_celebrity(4) 即可判断4是否真的为名人。
时间复杂度 O(n)
空间复杂度 O(1)
class Solution:
def findCelebrity(self, n: int) -> int:
self.n = n
celebrity_candidate = 0
for i in range(1, n):
if knows(celebrity_candidate, i):
celebrity_candidate = i
if self.is_celebrity(celebrity_candidate):
return celebrity_candidate
return -1
def is_celebrity(self, i):
for j in range(self.n):
if i == j: continue
if knows(i, j) or not knows(j, i):
return False
return True