Try to find a judge in a small town

Keywords: Javascript

Note: the code implementation of this article uses JS (JavaScript) to provide problem-solving ideas for small partners who want to use js to practice algorithms and data structures in the front end.

describe

In a small town, number n people from 1 to n. It is rumored that one of these people is a secret judge in the town. If the town judge really exists, then:

  • The town judge doesn't trust anyone.
  • Everyone (except the town judge) trusts the town judge.
  • Only one person meets both condition 1 and condition 2.

Given the array trust, which is composed of trust pair trust[i] = [a, b], indicating that the person with number a trusts the person with number B.

If there is a secret judge in the town and his identity can be determined, please return the judge's number. Otherwise, - 1 is returned.

Example:

Input: n = 2, trust = [[1,2]]
Output: 2
Input: n = 3, trust = [[1,3],[2,3]]
Output: 3
Input: n = 3, trust = [[1,3],[2,3],[3,1]]
Output:-1
Input: n = 3, trust = [[1,2],[2,3]]
Output:-1
Input: n = 4, trust = [[1,3],[1,4],[2,3],[2,4],[4,3]]
Output: 3

Tips:

  • 1 <= n <= 1000
  • 0 <= trust.length <= 104
  • trust[i].length == 2
  • trust[i] are different from each other
  • trust[i][0] != trust[i][1]
  • 1 <= trust[i][0], trust[i][1] <= n

Problem solving ideas

direct method

According to the ideas given in the body,

  • The judges in the town don't trust anyone: the first element of trust[i] can't be a judge.
  • Anyone (except the judge) believes in the judge: the set composed of the first element of the explanation trust[i] must include everyone except the judge; And if the judge exists, it must be in the set composed of the second element.
  1. Therefore, we can traverse the trust array, add ordinary people (except all judges) to the set people, and add people who may be judges to the trusted set.
    	let people = new Set()
        let trusted = new Set()
        for(let i = 0, len = trust.length; i < len; i++){
            people.add(trust[i][0])
            trusted.add(trust[i][1])
        }
    
  2. Then we need to find people who are not alternative, because they are likely to be judges
    	let alternative = []
        for(let i = 1; i <= n; i++)
            if(!people.has(i)) alternative.push(i)
    
  3. alternative then takes the intersection with the trusted person's set. If the intersection has only one element, it means that he is basically a judge; If it is not an element, there must be no judge
    	let rumors = alternative.filter(item => trusted.has(item))
        if(rumors.length !== 1) return -1
    
  4. Finally, check whether everyone trusts the judge, because in the first step, there is no guarantee that everyone trusts the judge
    let result = rumors[0]
        for(let i = 1; i <= n; i++){
            if(i !== result ) {
                if(!trust_str.has(i+''+result))
                return -1
            }
        }
    
    The complete code is as follows:
    var findJudge = function(n, trust) {
    	// If there is only one person and he doesn't believe anyone, he is a judge himself
        if(n === 1 && trust.length === 0) return 1
        let people = new Set()
        let trusted = new Set()
        // In order to determine whether everyone believes in the judge as the last step, the form of trust = [a,b] is changed to the string 'ab'
        // Can better judge a and believe b
        let trust_str = new Set()
        for(let i = 0, len = trust.length; i < len; i++){
            people.add(trust[i][0])
            trusted.add(trust[i][1])
            trust_str.add(trust[i].join(""))
        }
        let alternative = []
        for(let i = 1; i <= n; i++){
            if(!people.has(i)) alternative.push(i)
        }
        let rumors = alternative.filter(item => trusted.has(item))
        if(rumors.length !== 1) return -1
        let result = rumors[0]
        for(let i = 1; i <= n; i++){
            if(i !== result ) {
                if(!trust_str.has(i+''+result))
                return -1
            }
        }
        return result
    };
    
    This method is written purely according to the intuitive feeling in the brain, so the algorithm is very simple. It can be written according to logic. As for some processes during the period, readers may need to think about why.

Graph theory

We can regard the trust relationship as a graph. If a believes in b, it can be considered that there is an arrow from a to b. In this way, if there are n people, if b is a judge, there are n-1 arrows pointing to b, and b will not point to anyone. In other words, the judge's in degree is n-1 and out degree is 0.

The method of using objects to store in and out degrees is as follows:

var findJudge = function(n, trust) {
    if(n === 1 && trust.length === 0) return 1
    let in_obj = {}
    let out_obj = {}
    // Record everyone's entry and exit
    for(let i = 0, len = trust.length; i< len; i++){
        if(out_obj.hasOwnProperty(trust[i][0])) out_obj[trust[i][0]] ++
        else out_obj[trust[i][0]] = 1
        if(in_obj.hasOwnProperty(trust[i][1])) in_obj[trust[i][1]] ++
        else in_obj[trust[i][1]] = 1
    }
    // Find people with a penetration of n-1
    let in_set = new Set()
    for(const key in in_obj)
        if(in_obj[key] === n-1) in_set.add(key)
    // Among the people with a degree of n-1, find the one with a degree of 0, that is, out_ Not in BoJ
    for(const item of in_set)
        if(!(item in out_obj) return item
    // We didn't find anything that met the requirements
    return -1
};

The method of using an array to store in and out degrees is as follows:

var findJudge = function(n, trust) {
    let in_list = new Array(n+1).fill(0)
    let out_list = new Array(n+1).fill(0)
    for(const item of trust){
        in_list[item[1]] ++
        out_list[item[0]] ++
    }
    for(let i = 1; i <= n; i++)
        if(in_list[i] === n-1 && out_list[i] === 0)
            return i
    return -1
};

Posted by interpim on Sat, 18 Sep 2021 12:51:56 -0700