题目
标题和出处
标题:找到小镇的法官
出处:997. 找到小镇的法官
难度
3 级
题目描述
要求
小镇里有 n \texttt{n} n 个人,编号从 1 \texttt{1} 1 到 n \texttt{n} n。传言称,这些人中有一个暗地里是小镇法官。
如果小镇法官真的存在,那么:
- 小镇法官不会信任任何人。
- 每个人(除了小镇法官)都信任这位小镇法官。
- 只有一个人同时满足属性 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} 1≤n≤1000
- 0 ≤ trust.length ≤ 10 4 \texttt{0} \le \texttt{trust.length} \le \texttt{10}^\texttt{4} 0≤trust.length≤104
- 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} 1≤ai, bi≤n
解法
思路和算法
可以将小镇看成有向图,每个人是一个结点,每个信任关系是一条有向边。如果编号为 a a a 的人信任编号为 b b b 的人,则对应图中的从结点 a a a 指向结点 b b b 的有向边。每个人对应的结点的出度和入度分别表示这个人信任的人数和信任这个人的人数,遍历全部信任关系之后即可得到每个人对应的结点的出度和入度。
已知小镇里有 n n n 个人,根据小镇法官的定义,小镇法官对应的结点的出度是 0 0 0,入度是 n − 1 n - 1 n−1。当小镇法官存在时,由于除了小镇法官以外的每个人都信任小镇法官,因此除了小镇法官以外的每个人对应的结点的出度都大于 0 0 0,最多有 1 1 1 个小镇法官。
在得到每个人对应的结点的出度和入度之后,遍历每个人对应的结点,当遇到出度是 0 0 0 且入度是 n − 1 n - 1 n−1 的结点时,该结点编号的人即为小镇法官。如果不存在出度是 0 0 0 且入度是 n − 1 n - 1 n−1 的结点,则小镇法官不存在,返回 − 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 是小镇人数。需要记录每个人对应的结点的出度和入度。