【Leetcode刷题】277. Find the Celebrity 搜寻名人

【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
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值