sisterAn/JavaScript-Algorithms

leetcode997:找到小镇的法官

sisterAn opened this issue · 6 comments

在一个小镇里,按从 1N 标记了 N 个人。传言称,这些人中有一个是小镇上的秘密法官。

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

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

给定数组 trust ,该数组由信任对 trust[i] = [a, b] 组成,表示标记为 a 的人信任标记为 b 的人。

如果小镇存在秘密法官并且可以确定他的身份,请返回该法官的标记。否则,返回 -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

示例 4:

示例 4:

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

示例 5:

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

提示:

  • 1 <= N <= 1000
  • trust.length <= 10000
  • trust[i] 是完全不同的
  • trust[i][0] != trust[i][1]
  • 1 <= trust[i][0], trust[i][1] <= N

附赠leetcode可测试地址:leetcode

解答:利用图

本题是一道典型的有向图问题,不理解图的可以看这篇:初学者应该了解的数据结构 Graph,寻找法官即是寻找 入度为N-1,出度为0的点

let findJudge = function(N, trust) {
  //构造0-N个节点的图
  let graph = Array.from({length:N+1}, () => ({outDegree:0, inDegree:0}))
  trust.forEach(([a, b]) => {
    graph[a].outDegree++
    graph[b].inDegree++
  })
  return graph.findIndex(({outDegree, inDegree}, index) => {
    //剔除0
    return index != 0 && outDegree === 0 && inDegree === N-1 
  })
};

时间复杂度:O(N)

空间复杂度:O(N)

另一种解法:

其实法官也是唯一一个 出入度差值为 N-1 ,所以这里可以简化为寻找出入度差值为 N-1

let findJudge = function(N, trust) {
  let graph = Array(N+1).fill(0)
  // 出度加一
  // 入度减一
  trust.forEach(([a, b]) => {
    graph[a]--
    graph[b]++
  })
  return graph.findIndex((node, index) => {
    // 剔除0
    return index != 0 && node === N-1 
  })
};

时间复杂度:O(N)

空间复杂度:O(N)

leetcode

image

/**
 * @param {number} N
 * @param {number[][]} trust
 * @return {number}
 */
var findJudge = function(N, trust) {
    
    let inDegree = new Array(N).fill(0);
    let outDegree = new Array(N).fill(0);

    trust.forEach((_, index) => {
        inDegree[_[1] - 1]++;
        outDegree[_[0] - 1]++;
    })
    
    for(let i=0; i<N; i++){
        if(inDegree[i] == (N-1) && outDegree[i] == 0){
            return i + 1
        }
    }

    return -1
};
function getTrust(N,trust) {
	var trustObj = {};
	var beTrustObj = {};
	trust.forEach(item => {
		if(trustObj[item[0]]) {
			trustObj[item[0]] = trustObj[item[0]] + 1
		} else {
			trustObj[item[0]] = 1
		}
		if(beTrustObj[item[1]]) {
			beTrustObj[item[1]] += 1
		} else {
			beTrustObj[item[1]] = 1
		}
	})
	let has = -1
	for(let i = 1; i <= N; i++) {
		if(!trustObj[i] && beTrustObj[i] == N - 1) {
			has = i
		}
	}
	return has
}
  1. 代码比较简洁的写法
var findJudge = function(N, trust) {
  //很明显是图的问题,求出度为0,入度为N-1的那个节点,即法官
  //构造0-N个节点的图
  let graph = Array.from({length:N+1}, () => ({outDegree:0, inDegree:0}))
  trust.forEach(([a, b]) => {
    graph[a].outDegree++
    graph[b].inDegree++
  })
  return graph.findIndex(({outDegree, inDegree}, index) => {
    //避开第一个0;
    return index != 0 && outDegree == 0 && inDegree == N-1 
  })
};
  1. 其实我们不用计算出入度
var findJudge = function(N, trust) {
  //事实上我们真的有必要去算每个节点的出度入度嘛?
  //其实是不用的,我们只需要算出度和入度的差值是N-1即可
  //也就是说入度加1,出度减1;
  let graph = Array(N+1).fill(0)
  trust.forEach(([a, b]) => {
    graph[a]--
    graph[b]++
  })
  return graph.findIndex((node, index) => {
    return index != 0 && node == N-1 
  })
};
const fun = (N, trust) => {
    if(N===1) return 1
    const newTrust = []
    trust.forEach(([x,y])=>{
        newTrust[x] = -1
        newTrust[y] = newTrust[y] === undefined ? 1 : newTrust[y] ? ++newTrust[y] : -1
    })
    return newTrust.findIndex(val=>val===N-1)
}
zo11o commented
比较挫,就是很好理解
/**
 * @param {number} N
 * @param {number[][]} trust
 * @return {number}
 */
var findJudge = function (N, trust) {
    var ac = new Array(N).fill(1);
    // 通过所有标号构建一个数组
    var peoples = ac.map((o, i) => o + i)
    var map = {}

    if (N == 1 && !trust.length) {
        return [1]
    }

    for (let i = 0; i < trust.length; i++) {
        let idx = peoples.indexOf(trust[i][0])
        //  由于法官没有信任的人,那就数组中移除有信任人的元素
        if (idx !== -1) {
            peoples.splice(idx, 1)
        }
        if (map[trust[i][1]] != null) {
            map[trust[i][1]] = map[trust[i][1]] + 1
        } else {
            map[trust[i][1]] = 1
        }
    }

    for (let i = 0; i < peoples.length; i++) {
        if (map[peoples[i]] === N - 1) {
            return peoples[i]
        }
    }

    return -1
};