LeetCode探索(79):997-找到小镇的法官

164 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

题目

小镇里有 n 个人,按从 1n 的顺序编号。传言称,这些人中有一个暗地里是小镇法官。

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

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

给你一个数组 trust ,其中 trust[i] = [ai, bi] 表示编号为 ai 的人信任编号为 bi 的人。

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

示例 1:

输入:n = 2, trust = [[1,2]]
输出:2

示例 2:

输入:n = 3, trust = [[1,3],[2,3]]
输出:3

示例 3:

输入:n = 3, trust = [[1,3],[2,3],[3,1]]
输出:-1

提示:

  • 1 <= n <= 1000
  • 0 <= trust.length <= 10^4
  • trust[i].length == 2
  • trust 中的所有trust[i] = [ai, bi] 互不相同
  • ai != bi
  • 1 <= ai, bi <= n

思考

本题难度中等。

首先是读懂题意。小镇上有 1 ~ n 共 n 个人,小镇法官的定义是:

  • 小镇法官不会信任任何人。

  • 每个人(除了小镇法官)都信任这位小镇法官。

  • 只有一个人同时满足属性 1 和属性 2。

又因为存在数组 trust ,其中 trust[i] = [ai, bi] 表示编号为 ai 的人信任编号为 bi 的人。

因此,我们可以通过计数的方法解决问题。我们需要找出trust[i][1],其出现次数应该是n-1,且不在trust[i][0]出现过。为了方便统计,在trust[i][0]出现过则次数-1,在trust[i][1]出现过则次数+1。最后,遍历比较是否有出现次数为n-1的,问题解决!

我们也可以借助有向图的概念。在有向图中,一个节点的入度是指向该节点的边的数量;而一个节点的出度是从该节点出发的边的数量。由题意可知,法官这个节点的入度是 n-1, 出度是 0。我们可以遍历每个节点的入度和出度,如果找到一个符合条件的节点,直接返回结果;如果不存在符合条件的点,则返回 −1。

解答

方法一:有向图

/**
 * @param {number} n
 * @param {number[][]} trust
 * @return {number}
 */
var findJudge = function(n, trust) {
  const inDegrees = new Array(n + 1).fill(0)
  const outDegrees = new Array(n + 1).fill(0)
  for (const edge of trust) {
    const x = edge[0], y = edge[1]
    ++inDegrees[y]
    ++outDegrees[x]
  }
  for (let i = 1; i <= n; ++i) {
    if (inDegrees[i] === n - 1 && outDegrees[i] === 0) {
      return i
    }
  }
  return -1
}
// 执行用时:80 ms, 在所有 JavaScript 提交中击败了94.17%的用户
// 内存消耗:49.4 MB, 在所有 JavaScript 提交中击败了60.06%的用户
// 通过测试用例:92 / 92

复杂度分析:

  • 时间复杂度:O(n+m),其中 m 是 trust 的长度。
  • 空间复杂度:O(n)。

参考