图题目:找到小镇的法官

文章讨论了一个关于找出小镇法官的问题,利用有向图模型来表示信任关系,通过计算每个人的信任度(出度和入度)来判断法官身份,时间复杂度为O(n+m)。
摘要由CSDN通过智能技术生成

题目

标题和出处

标题:找到小镇的法官

出处:997. 找到小镇的法官

难度

3 级

题目描述

要求

小镇里有 n \texttt{n} n 个人,编号从 1 \texttt{1} 1 n \texttt{n} n。传言称,这些人中有一个暗地里是小镇法官。

如果小镇法官真的存在,那么:

  1. 小镇法官不会信任任何人。
  2. 每个人(除了小镇法官)都信任这位小镇法官。
  3. 只有一个人同时满足属性 1 和属性 2

给定一个数组 trust \texttt{trust} trust,其中 trust[i]   =   [a i ,   b i ] \texttt{trust[i] = [a}_\texttt{i}\texttt{, b}_\texttt{i}\texttt{]} trust[i] = [ai, bi] 表示编号为 a i \texttt{a}_\texttt{i} ai 的人信任编号为 b i \texttt{b}_\texttt{i} bi 的人。

如果小镇法官存在并且可以确定他的身份,请返回该法官的编号,否则返回 -1 \texttt{-1} -1

示例

示例 1:

输入: n   =   2,   trust   =   [[1,2]] \texttt{n = 2, trust = [[1,2]]} n = 2, trust = [[1,2]]
输出: 2 \texttt{2} 2

示例 2:

输入: n   =   3,   trust   =   [[1,3],[2,3]] \texttt{n = 3, trust = [[1,3],[2,3]]} n = 3, trust = [[1,3],[2,3]]
输出: 3 \texttt{3} 3

示例 3:

输入: n   =   3,   trust   =   [[1,3],[2,3],[3,1]] \texttt{n = 3, trust = [[1,3],[2,3],[3,1]]} n = 3, trust = [[1,3],[2,3],[3,1]]
输出: -1 \texttt{-1} -1

数据范围

  • 1 ≤ n ≤ 1000 \texttt{1} \le \texttt{n} \le \texttt{1000} 1n1000
  • 0 ≤ trust.length ≤ 10 4 \texttt{0} \le \texttt{trust.length} \le \texttt{10}^\texttt{4} 0trust.length104
  • trust[i].length = 2 \texttt{trust[i].length} = \texttt{2} trust[i].length=2
  • trust \texttt{trust} trust 中的所有编号对各不相同
  • a i ≠ b i \texttt{a}_\texttt{i} \ne \texttt{b}_\texttt{i} ai=bi
  • 1 ≤ a i ,   b i ≤ n \texttt{1} \le \texttt{a}_\texttt{i}\texttt{, b}_\texttt{i} \le \texttt{n} 1ai, bin

解法

思路和算法

可以将小镇看成有向图,每个人是一个结点,每个信任关系是一条有向边。如果编号为 a a a 的人信任编号为 b b b 的人,则对应图中的从结点 a a a 指向结点 b b b 的有向边。每个人对应的结点的出度和入度分别表示这个人信任的人数和信任这个人的人数,遍历全部信任关系之后即可得到每个人对应的结点的出度和入度。

已知小镇里有 n n n 个人,根据小镇法官的定义,小镇法官对应的结点的出度是 0 0 0,入度是 n − 1 n - 1 n1。当小镇法官存在时,由于除了小镇法官以外的每个人都信任小镇法官,因此除了小镇法官以外的每个人对应的结点的出度都大于 0 0 0,最多有 1 1 1 个小镇法官。

在得到每个人对应的结点的出度和入度之后,遍历每个人对应的结点,当遇到出度是 0 0 0 且入度是 n − 1 n - 1 n1 的结点时,该结点编号的人即为小镇法官。如果不存在出度是 0 0 0 且入度是 n − 1 n - 1 n1 的结点,则小镇法官不存在,返回 − 1 -1 1

代码

class Solution {
    public int findJudge(int n, int[][] trust) {
        int[] outdegrees = new int[n + 1];
        int[] indegrees = new int[n + 1];
        for (int[] edge : trust) {
            outdegrees[edge[0]]++;
            indegrees[edge[1]]++;
        }
        for (int i = 1; i <= n; i++) {
            if (outdegrees[i] == 0 && indegrees[i] == n - 1) {
                return i;
            }
        }
        return -1;
    }
}

复杂度分析

  • 时间复杂度: O ( n + m ) O(n + m) O(n+m),其中 n n n 是小镇人数, m m m 是数组 trust \textit{trust} trust 的长度。需要遍历图中的每条边和每个结点一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是小镇人数。需要记录每个人对应的结点的出度和入度。

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的车尔尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值