The Celebrity Problem

In this tutorial, we will learn about the celebrity problem. We will solve this problem using the various methods. This is an important programming problem that can be asked in the technical interview. This tutorial will help you learn to solve it efficiently. Let's understand the problem statement.

There are N people in a party, only one person who is known to everyone, but this person doesn't know anyone else. We need to find out if A knows B or in other words, we need to identify this "stranger" or "celebrity" using the fewest possible questions.

The problem is represented by an array of numbers or characters, symbolizing the people at the party. We have a function called HaveAcquaintance(A, B) that, when given two individuals A and B, tells us whether A knows B (returns true) or not (returns false).

Example 1:

Input:

MATRIX = [[0, 0, 1, 0, 1],

[0, 0, 1, 0, 0],

[0, 1, 0, 1, 1],

[0, 0, 1, 0, 0],

[0, 1, 1, 0, 0]]

Output: id = 3

Explanation: In this case, a person with ID 3 does not know anyone at the party, and everyone knows them.

Example 2:

Input:

MATRIX = [[0, 0, 1, 0, 1],

[0, 0, 1, 0, 0],

[0, 1, 0, 1, 1],

[0, 0, 1, 0, 1],

[0, 1, 1, 0, 0]]

Output: No celebrity

Explanation: In this scenario, there is no celebrity.

Basic and Utilizing Adjacency Lists Approach

We're given a square matrix M[][] of size NxN to represent relationships among people at a party. In this matrix, if M[i][j] is set to 1, it means the ith person knows the jth person. We treat this as a directed graph and construct an adjacency list. Then, we check if any person has an empty adjacency list, indicating they don't know anyone at the party. If this is the case, we verify if everyone else at the party knows that person. If they do, we consider that person as the celebrity and return their index i. If not, we continue searching for the celebrity.

To solve the problem, follow these steps:

  1. First, we iterate the given matrix and create an adjacency list.
  2. If M[i][j] is 1, add a directed edge from person i to person j in the adjacency list.
  3. Next, iterate from 0 to n (the number of people at the party).
  4. Check if the adjacency list of person i is empty.
  5. If it's empty, examine whether everyone else in the party knows person i.
  6. If all other people have a connection to person i, consider them the celebrity and return their index, i.

Let's understand the following example -

Example -

Output

2

Explanation -

In the above code we have followed the below steps -

  1. We define the findCelebrity() function, which takes a matrix M as input which gets the size of the matrix M to determine the number of people at the party (N). Then we initialize n to the number of rows (or columns) in the matrix.
  2. After that, we create an empty list `adj` to represent an adjacency list. Each element of this list will contain the list of people that the corresponding person knows.
  3. Then we fill the adjacency list (adj) based on the values in the matrix `M`. For each cell `M[i][j]` where `M[i][j] == 1`, it means that person `i` knows person `j`, so we add `j` to the adjacency list of person `i`.
  4. We iterate through each person, denoted by the index i from 0 to n-1.
  5. For each person i, check if their adjacency list is empty. An empty adjacency list means that person i does not know anyone at the party.
  6. If the adjacency list of person i is empty, it means person i could potentially be a celebrity. To confirm, we check whether person i is known by all the other people in the party.
  7. We iterate through all the other people (denoted by `j`) from 0 to n-1. If i is not equal to j and j is not in the adjacency list of person i, it means that person j does not know person i. In this case, we can conclude that person i is not a celebrity.
  8. If, after checking all other people, we find that no one knows person `i`, we consider person `i` as the celebrity and return their index, which is `i`. If no celebrity is found after checking all people, return "No celebrity."

The Celebrity Problem: Utilizing Graphs for Identification

Follow these steps to solve the problem:

  1. We create two arrays, indegree and outdegree to keep track of the number of incoming and outgoing connections.
  2. Then we use two nested loops: the outer loop runs from 0 to n, and the inner loop also runs from 0 to n.
  3. For each pair of individuals, i and j, perform the following checks:
    1. If person i knows person j, increase the outdegree of person i and the indegree of person j.
    2. If person j knows person i, increase the outdegree of person j and the indegree of person i.
  4. Run a loop from 0 to n to find the individual ID where the indegree is n-1 (indicating that this person is known by all others) and the outdegree is 0 (indicating that this person doesn't know anyone).

Let's understand the following code -

Example -

Output

The celebrity is person with ID 2

Explanation -

Let's understand the above code:

  1. We initialize indegree and outdegree arrays to keep track of the number of people who know each person and the number of people they know.
  2. Then we iterate through each pair of individuals (i, j) using two nested loops. These loops represent every possible pair of people in the party.
  3. For each pair (i, j). We check if person i knows person j by examining MATRIX[i][j]. If MATRIX[i][j] is 1, it means person i knows person j.
  4. If person i knows person j, increment the outdegree of person i and the indegree of person j. This step helps keep track of how many people each individual knows and how many people know each individual.
  5. After processing all pairs (i, j), the `indegree` and `outdegree` arrays are filled.
  6. We iterate through all individuals (from 0 to n) and check if any individual satisfies the conditions for being a celebrity:
  7. We check if their indegree is equal to `n - 1`. If it is, it means that all other people know this individual because a celebrity should be known by everyone except themselves.
  8. Check if their outdegree is 0. This means that the individual doesn't know anyone in the party.
  9. If an individual is found who meets these conditions, they are considered a celebrity and their ID is returned.
  10. If no celebrity is found after checking all individuals, the code returns -1 to indicate that there is no celebrity in the party.

Using Recursion

We can solve this problem using the recursion. If the potential celebrity of N-1 person is known, it can be possible to find solution to N from it. A potential celebrity is someone who remains eliminated when n-1 people are removed using the following rule:

  • If A knows B, A cannot be a celebrity, but B might be.
  • If B knows A, B cannot be a celebrity, but A might be.

Following are of the steps to achieve recursion -

  1. First, we create a recursive function that takes an integer n as input.
  2. We check the base case: If n equals 0, return -1.
  3. We call the recursive function with the first n-1 elements to find the potential celebrity's ID.
  4. If the ID from step 3 is -1, assign n as the potential celebrity's ID and return n.
  5. If the potential celebrity of the first n-1 elements knows n-1, return n-1 (using 0-based indexing).
  6. If the celebrity of the first n-1 elements does not know n-1, return the ID of the celebrity from the n-1 elements (using 0-based indexing).
  7. If none of the conditions in steps 4, 5, and 6 apply, return -1.
  8. Then, Create a wrapper function and check whether the ID returned by the recursive function is indeed the celebrity.

Let's understand the following code snippet.

Example -

Output

Celebrity ID: 2

Conclusion

In this code, we find the celebrity in a party by checking if someone doesn't know anyone but is known by everyone. We use two arrays, indegree and outdegree, to keep track of who knows and is known by whom. By comparing these values, we identify the celebrity. If such a person exists, their ID is returned. If not, we conclude that there's no celebrity in the party. This code efficiently solves the celebrity problem, a common interview question in technical round.