997. Find the Town Judge
Problem Description
This problem asks you to identify the "town judge" among n
people labeled from 1
to n
.
The town judge has two unique characteristics:
- The judge trusts nobody - they don't trust any other person in the town
- Everyone else trusts the judge - all other
n-1
people trust the judge
You're given an array trust
where each element trust[i] = [ai, bi]
means person ai
trusts person bi
. The trust relationships are directional - if person A trusts person B, it doesn't mean B trusts A.
Your task is to find and return the label of the town judge if such a person exists. If no valid judge can be identified, return -1
.
For example:
- If
n = 3
andtrust = [[1,3], [2,3]]
, person 3 is the judge because:- Person 3 trusts nobody (no entries with 3 as the first element)
- Everyone else (persons 1 and 2) trusts person 3
The solution uses two counting arrays:
cnt1[i]
tracks how many people personi
trusts (outgoing trust)cnt2[i]
tracks how many people trust personi
(incoming trust)
A person i
is the judge if and only if cnt1[i] == 0
(trusts nobody) and cnt2[i] == n-1
(trusted by everyone else).
Intuition
The key insight is to think about trust relationships as a directed graph where each person is a node and each trust relationship is a directed edge from the person who trusts to the person being trusted.
In this graph representation, the town judge would have a very specific pattern:
- In-degree: The judge receives
n-1
incoming edges (everyone else trusts them) - Out-degree: The judge has
0
outgoing edges (they trust nobody)
This immediately suggests we need to track two pieces of information for each person:
- How many people they trust (out-degree)
- How many people trust them (in-degree)
Instead of building an actual graph, we can simplify this to just counting. For each trust relationship [a, b]
:
- Person
a
trusts someone, so increment their "trusts count" - Person
b
is trusted by someone, so increment their "trusted by count"
After processing all trust relationships, we can identify the judge by finding the person who:
- Has a "trusts count" of
0
(trusts nobody) - Has a "trusted by count" of
n-1
(trusted by everyone else)
This counting approach is efficient because we only need to traverse the trust array once to build our counts, then check each person once to find the judge. The uniqueness of the judge (if they exist) is guaranteed by the problem constraints, so we can return immediately when we find someone matching our criteria.
Learn more about Graph patterns.
Solution Approach
The solution uses a counting approach with two arrays to track trust relationships.
Step 1: Initialize Counting Arrays
We create two arrays cnt1
and cnt2
, both of size n + 1
:
cnt1[i]
tracks how many people personi
trusts (out-degree)cnt2[i]
tracks how many people trust personi
(in-degree)
We use size n + 1
to directly map person labels (1 to n) to array indices, leaving index 0 unused.
Step 2: Process Trust Relationships
For each trust relationship [a, b]
in the trust
array:
- Increment
cnt1[a]
by 1 (persona
trusts someone) - Increment
cnt2[b]
by 1 (personb
is trusted by someone)
for a, b in trust: cnt1[a] += 1 # a trusts someone cnt2[b] += 1 # b is trusted by someone
Step 3: Identify the Judge
Iterate through all people from 1 to n and check if person i
satisfies both conditions:
cnt1[i] == 0
: Personi
trusts nobodycnt2[i] == n - 1
: Personi
is trusted by all othern-1
people
for i in range(1, n + 1):
if cnt1[i] == 0 and cnt2[i] == n - 1:
return i
If we find such a person, we immediately return their label as they are the judge. If no person satisfies both conditions after checking everyone, we return -1
to indicate no judge exists.
Time Complexity: O(E + n)
where E is the number of trust relationships (edges)
Space Complexity: O(n)
for the two counting arrays
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example with n = 4
people and trust = [[1,3], [1,4], [2,3], [2,4], [4,3]]
.
Step 1: Initialize Arrays We create two arrays of size 5 (indices 0-4, where index 0 is unused):
cnt1 = [0, 0, 0, 0, 0]
(tracks who each person trusts)cnt2 = [0, 0, 0, 0, 0]
(tracks who trusts each person)
Step 2: Process Each Trust Relationship
Processing [1,3]
: Person 1 trusts Person 3
cnt1[1]++
βcnt1 = [0, 1, 0, 0, 0]
cnt2[3]++
βcnt2 = [0, 0, 0, 1, 0]
Processing [1,4]
: Person 1 trusts Person 4
cnt1[1]++
βcnt1 = [0, 2, 0, 0, 0]
cnt2[4]++
βcnt2 = [0, 0, 0, 1, 1]
Processing [2,3]
: Person 2 trusts Person 3
cnt1[2]++
βcnt1 = [0, 2, 1, 0, 0]
cnt2[3]++
βcnt2 = [0, 0, 0, 2, 1]
Processing [2,4]
: Person 2 trusts Person 4
cnt1[2]++
βcnt1 = [0, 2, 2, 0, 0]
cnt2[4]++
βcnt2 = [0, 0, 0, 2, 2]
Processing [4,3]
: Person 4 trusts Person 3
cnt1[4]++
βcnt1 = [0, 2, 2, 0, 1]
cnt2[3]++
βcnt2 = [0, 0, 0, 3, 2]
Final arrays:
cnt1 = [0, 2, 2, 0, 1]
(Person 1 trusts 2 people, Person 2 trusts 2 people, Person 3 trusts 0 people, Person 4 trusts 1 person)cnt2 = [0, 0, 0, 3, 2]
(Person 3 is trusted by 3 people, Person 4 is trusted by 2 people)
Step 3: Find the Judge
Check each person (1 to 4):
- Person 1:
cnt1[1] = 2
(trusts 2 people) andcnt2[1] = 0
(trusted by 0 people) β Not the judge - Person 2:
cnt1[2] = 2
(trusts 2 people) andcnt2[2] = 0
(trusted by 0 people) β Not the judge - Person 3:
cnt1[3] = 0
(trusts nobody) andcnt2[3] = 3
(trusted by 3 people) β This matches! (0 == 0 β and 3 == n-1 β) - Person 4:
cnt1[4] = 1
(trusts 1 person) andcnt2[4] = 2
(trusted by 2 people) β Not the judge
Result: Person 3 is the town judge because they trust nobody and are trusted by all other 3 people.
Solution Implementation
1class Solution:
2 def findJudge(self, n: int, trust: List[List[int]]) -> int:
3 # Initialize arrays to track trust relationships
4 # out_degree[i] = number of people that person i trusts
5 # in_degree[i] = number of people who trust person i
6 out_degree = [0] * (n + 1) # Index 0 unused, people numbered 1 to n
7 in_degree = [0] * (n + 1)
8
9 # Count trust relationships for each person
10 for truster, trusted in trust:
11 out_degree[truster] += 1 # Person 'truster' trusts someone
12 in_degree[trusted] += 1 # Person 'trusted' is trusted by someone
13
14 # Find the town judge
15 # The judge trusts nobody (out_degree = 0) and is trusted by everyone else (in_degree = n-1)
16 for person in range(1, n + 1):
17 if out_degree[person] == 0 and in_degree[person] == n - 1:
18 return person
19
20 # No judge found
21 return -1
22
1class Solution {
2 public int findJudge(int n, int[][] trust) {
3 // Array to track how many people each person trusts (outgoing trust)
4 int[] trustsOthers = new int[n + 1];
5 // Array to track how many people trust each person (incoming trust)
6 int[] trustedByOthers = new int[n + 1];
7
8 // Process each trust relationship
9 for (int[] trustRelation : trust) {
10 int personWhoTrusts = trustRelation[0];
11 int personBeingTrusted = trustRelation[1];
12
13 // Increment the count of people that personWhoTrusts trusts
14 trustsOthers[personWhoTrusts]++;
15 // Increment the count of people who trust personBeingTrusted
16 trustedByOthers[personBeingTrusted]++;
17 }
18
19 // Find the town judge
20 // The judge trusts nobody (trustsOthers[i] == 0)
21 // Everyone else trusts the judge (trustedByOthers[i] == n - 1)
22 for (int person = 1; person <= n; person++) {
23 if (trustsOthers[person] == 0 && trustedByOthers[person] == n - 1) {
24 return person;
25 }
26 }
27
28 // No judge found
29 return -1;
30 }
31}
32
1class Solution {
2public:
3 int findJudge(int n, vector<vector<int>>& trust) {
4 // Initialize arrays to track trust relationships
5 // outgoingTrust[i]: number of people that person i trusts
6 // incomingTrust[i]: number of people who trust person i
7 vector<int> outgoingTrust(n + 1);
8 vector<int> incomingTrust(n + 1);
9
10 // Process each trust relationship
11 for (auto& trustRelation : trust) {
12 int truster = trustRelation[0];
13 int trusted = trustRelation[1];
14
15 // Person 'truster' trusts someone, increment their outgoing trust count
16 ++outgoingTrust[truster];
17
18 // Person 'trusted' is trusted by someone, increment their incoming trust count
19 ++incomingTrust[trusted];
20 }
21
22 // Find the town judge
23 // The judge must satisfy two conditions:
24 // 1. Trusts nobody (outgoingTrust == 0)
25 // 2. Is trusted by everyone else (incomingTrust == n - 1)
26 for (int person = 1; person <= n; ++person) {
27 if (outgoingTrust[person] == 0 && incomingTrust[person] == n - 1) {
28 return person;
29 }
30 }
31
32 // No judge found
33 return -1;
34 }
35};
36
1/**
2 * Finds the town judge based on trust relationships
3 * @param n - Number of people in the town (labeled from 1 to n)
4 * @param trust - Array of trust relationships where trust[i] = [a, b] means person a trusts person b
5 * @returns The label of the town judge if exists, otherwise -1
6 */
7function findJudge(n: number, trust: number[][]): number {
8 // Array to track how many people each person trusts (outgoing trust)
9 const trustsOthersCount: number[] = new Array(n + 1).fill(0);
10
11 // Array to track how many people trust each person (incoming trust)
12 const trustedByOthersCount: number[] = new Array(n + 1).fill(0);
13
14 // Count trust relationships for each person
15 for (const [truster, trustee] of trust) {
16 trustsOthersCount[truster]++; // Person 'truster' trusts someone
17 trustedByOthersCount[trustee]++; // Person 'trustee' is trusted by someone
18 }
19
20 // Find the judge: someone who trusts nobody but is trusted by everyone else
21 for (let person = 1; person <= n; person++) {
22 if (trustsOthersCount[person] === 0 && trustedByOthersCount[person] === n - 1) {
23 return person;
24 }
25 }
26
27 // No judge found
28 return -1;
29}
30
Time and Space Complexity
The time complexity is O(m + n)
, where m
is the length of the trust
array and n
is the number of people. The algorithm iterates through the trust
array once to populate the count arrays (O(m)
), then iterates through all n
people to find the judge (O(n)
), resulting in O(m + n)
total time complexity.
The space complexity is O(n)
, where n
is the number of people. The algorithm uses two arrays cnt1
and cnt2
, each of size n + 1
, to track the trust relationships. Since these are fixed-size arrays that depend only on the number of people and not on the number of trust relationships, the space complexity is O(n)
.
Note: The reference answer states the complexity in terms of n
being the length of the trust
array, but this appears to be a notation inconsistency. In the context of this problem, n
represents the number of people (as used in the function parameter), and the length of the trust
array would be better represented as m
or |trust|
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Using a Single Array Instead of Two
A common mistake is trying to use a single array to track the "trust balance" (in-degree minus out-degree). While this might seem clever, it fails to distinguish between different scenarios that produce the same balance.
Incorrect Approach:
def findJudge(self, n: int, trust: List[List[int]]) -> int:
balance = [0] * (n + 1)
for a, b in trust:
balance[a] -= 1 # a trusts someone
balance[b] += 1 # b is trusted
for i in range(1, n + 1):
if balance[i] == n - 1: # Wrong check!
return i
return -1
Why it fails: A person with balance n-1
might trust one person and be trusted by everyone. For example, if person A trusts B and everyone (including B) trusts A, person A would have a balance of n-1
but isn't the judge because they trust someone.
Correct Solution: Always use two separate arrays to independently track outgoing and incoming trust relationships.
2. Off-by-One Errors with Array Indexing
Since people are numbered from 1 to n, but arrays are 0-indexed, it's easy to make indexing mistakes.
Common Mistakes:
- Creating arrays of size
n
instead ofn + 1
- Starting iteration from 0 instead of 1
- Forgetting that index 0 is unused
Correct Implementation:
# Correct: size n + 1 to accommodate people labeled 1 to n
out_degree = [0] * (n + 1)
in_degree = [0] * (n + 1)
# Correct: iterate from 1 to n (inclusive)
for person in range(1, n + 1):
# Check conditions
3. Edge Case: Single Person (n = 1)
When there's only one person in town, they are automatically the judge since:
- They trust nobody (trivially true)
- Everyone else trusts them (vacuously true, as there are 0 other people)
Potential Issue: If the trust array is empty and n = 1, ensure your code correctly returns 1, not -1.
Test this edge case:
assert findJudge(1, []) == 1 # Single person is the judge assert findJudge(2, []) == -1 # Two people, no trust = no judge
In a binary min heap, the minimum element can be found in:
Recommended Readings
https assets algo monster cover_photos graph svg Graph Fundamentals Tree with 0 cycle At this point you should be pretty familiar with trees A tree is a special kind of graph a connected acyclic cycle less graph A graph may contain cycle s and nodes could be disconnected A tree
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!