LeetCode第277题_寻找名人

LeetCode 第277题:寻找名人

📖 文章摘要

本文详细解析LeetCode第277题"寻找名人",这是一道经典的图论和逻辑推理问题。文章提供了双指针和图论两种解题思路,包含C#、Python、C++三种语言实现,配有详细的分析表格和性能对比。适合学习图论和逻辑推理算法的读者。

核心知识点: 图论、双指针、逻辑推理
难度等级: 中等
推荐人群: 具备基础算法知识,想要提升逻辑思维能力的开发者

题目描述

假设你是一个专业的狗仔,参加了一个 n 人派对,其中每个人被从 0n - 1 标号。在这个派对中,只有一个 “名人”。所谓 “名人” 的定义是:

  1. 所有其他人都认识他/她
  2. 他/她不认识任何其他人

现在你想要确认这个 “名人” 是谁,或者确定这个 “名人” 不存在。而你只能问诸如 “A 你好呀,请问你认识 B 吗?” 的问题。你需要尽可能少的问题来确定这个 “名人” 是谁(或者确定这个 “名人” 不存在)。

在本题中,你可以使用辅助函数 bool Knows(int a, int b) 获取到 A 是否认识 B。请你来实现一个函数 int FindCelebrity(int n)

派对最多只会有一个 “名人” 参加。若 “名人” 存在,请返回他/她的编号;若 “名人” 不存在,请返回 -1

示例

示例 1:

输入:graph = [[1,1,0],[0,1,0],[1,1,1]]
输出:1
解释:2号人认识所有人,但1号人不认识2号人,所以2号人不是名人。
1号人不认识2号人,但其他人都认识1号人,所以1号人是名人。
0号人认识1号人,所以0号人不是名人。
因此,1号人是名人。

示例 2:

输入:graph = [[1,0,1],[1,1,0],[0,1,1]]
输出:-1
解释:没有名人。

提示

  • n == graph.length == graph[i].length
  • 2 <= n <= 100
  • graph[i][j]01
  • graph[i][i] == 1

解题思路

本题可以使用双指针方法来解决,主要思路如下:

  1. 首先假设0号是名人候选人
  2. 遍历所有人,如果当前候选人认识某人,那么候选人一定不是名人,将认识的那个人设为新的候选人
  3. 最后需要验证候选人是否真的是名人:
    • 确保所有其他人都认识候选人
    • 确保候选人不认识任何其他人

图解思路

候选人筛选过程分析表

当前位置候选人比较对象Knows(候选人,比较对象)新候选人说明
001true10认识1,0不是名人
112false11不认识2,1可能是名人
21--1遍历结束,1是候选人

名人验证分析表

验证步骤检查内容条件结果说明
第一步候选人不认识任何人Knows(候选人,i)==false通过遍历检查候选人是否认识其他人
第二步所有人都认识候选人Knows(i,候选人)==true通过遍历检查其他人是否都认识候选人
结论候选人是名人两个条件都满足是名人返回候选人编号

代码实现

C# 实现

public class Solution : Relation {
    public int FindCelebrity(int n) {
        // 找到候选人
        int candidate = 0;
        for (int i = 1; i < n; i++) {
            if (Knows(candidate, i)) {
                candidate = i;
            }
        }
        
        // 验证候选人是否是名人
        for (int i = 0; i < n; i++) {
            if (i != candidate) {
                // 如果候选人认识其他人,或其他人不认识候选人
                if (Knows(candidate, i) || !Knows(i, candidate)) {
                    return -1;
                }
            }
        }
        
        return candidate;
    }
}

Python 实现

class Solution(object):
    def findCelebrity(self, n):
        """
        :type n: int
        :rtype: int
        """
        # 找到候选人
        candidate = 0
        for i in range(1, n):
            if knows(candidate, i):
                candidate = i
        
        # 验证候选人
        for i in range(n):
            if i != candidate:
                if knows(candidate, i) or not knows(i, candidate):
                    return -1
        
        return candidate

C++ 实现

class Solution : public Relation {
public:
    int findCelebrity(int n) {
        // 找到候选人
        int candidate = 0;
        for (int i = 1; i < n; i++) {
            if (knows(candidate, i)) {
                candidate = i;
            }
        }
        
        // 验证候选人
        for (int i = 0; i < n; i++) {
            if (i != candidate) {
                if (knows(candidate, i) || !knows(i, candidate)) {
                    return -1;
                }
            }
        }
        
        return candidate;
    }
};

执行结果

C# 实现

  • 执行用时:92 ms
  • 内存消耗:39.8 MB

Python 实现

  • 执行用时:112 ms
  • 内存消耗:14.2 MB

C++ 实现

  • 执行用时:76 ms
  • 内存消耗:9.5 MB

性能对比

语言执行用时内存消耗特点
C#92 ms39.8 MB代码结构清晰,性能适中
Python112 ms14.2 MB代码最简洁,但运行较慢
C++76 ms9.5 MB性能最优,内存占用最小

代码亮点

  1. 🎯 使用双指针优化时间复杂度为O(n)
  2. 💡 巧妙利用逻辑推理减少API调用次数
  3. 🔍 分两步验证确保结果正确性
  4. 🎨 代码结构清晰,逻辑分明

常见错误分析

  1. 🚫 忘记验证候选人是否真的是名人
  2. 🚫 验证过程中遗漏某些情况的检查
  3. 🚫 未考虑没有名人的情况
  4. 🚫 API调用次数过多导致性能下降

解法对比

解法时间复杂度空间复杂度优点缺点
暴力解法O(n^2)O(1)思路简单直观API调用次数多
双指针法O(n)O(1)API调用次数少代码略复杂
图论解法O(n^2)O(n^2)易于理解空间复杂度高

相关题目

📖 系列导航

🔥 算法专题合集 - 查看完整合集

📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新第277题。

💬 互动交流

感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。

如果这篇文章对你有帮助,请:

  • 👍 点个赞,让更多人看到这篇文章
  • 📁 收藏文章,方便后续查阅复习
  • 🔔 关注作者,获取更多高质量算法题解
  • 💭 评论区留言,分享你的解题思路或提出疑问

你的支持是我持续分享的动力!

💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值