The Celebrity Problem
Last Updated :
18 Sep, 2023
In a party of N people, only one person is known to everyone. Such a person may be present at the party, if yes, (s)he doesn’t know anyone at the party. We can only ask questions like “does A know B? “. Find the stranger (celebrity) in the minimum number of questions.
We can describe the problem input as an array of numbers/characters representing persons in the party. We also have a hypothetical function HaveAcquaintance(A, B) which returns true if A knows B, and false otherwise. How can we solve the problem?
Examples:
Input:
MATRIX = { {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}, {0, 0, 1, 0} }
Output: id = 2
Explanation: The person with ID 2 does not know anyone but everyone knows him
Input:
MATRIX = { {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 1, 0} }
Output: No celebrity
Explanation: There is no celebrity.
Approach :
As we are given A square NxN matrix M[][] is used to represent people at the party such that if an element of row i and column j is set to 1 ( M[i][j] = 1) it means ith person knows jth person. So it is an Directed Graph we create adjacency list and check for if any adjacency list empty means the person do not know any one in party then we check if all other person in party know him then the person(i) is celebrity return index i if not then find continue.
Follow the steps below to solve the problem :
- traverse over given matrix and make adjacency list.
- make a directed edge from i to j if m[i][j]==1 in adjacency list.
- now we need to traverse over 0 to n.
- and check weather adj[i].empty() if true then check that i is present in all other adjacency list from 0 to n.
- if all other person know i then he is celebrity simply return i.
- if know one satisfy above condition retrun -1.
Below is the implementation of the above approach :
C++
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int celebrity(vector<vector< int >>&M, int n){
vector< int >adj[n+1];
for ( int i=0;i<n;i++){
for ( int j=0;j<n;j++){
if (M[i][j]==1){
adj[i].push_back(j);
}
}
}
vector< int >::iterator it;
for ( int i=0;i<n;i++){
if (adj[i].empty()){
bool flag=1;
for ( int j=0;j<n;j++){
if (i==j) continue ;
it=find(adj[j].begin(),adj[j].end(),i);
if (it==adj[j].end()){
flag=0;
break ;
}
}
if (flag) return i;
}
}
return -1;
}
int main() {
vector<vector< int >>M{ {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}, {0, 0, 1, 0} };
int n=M.size();
int Celebrity=celebrity(M,n);
if (Celebrity!=-1){
cout<< "Celebrity is : " <<Celebrity<<endl;
} else {
cout<< "No celebrity" <<endl;
}
return 0;
}
|
Java
import java.util.*;
public class Main {
public static int celebrity(ArrayList<ArrayList<Integer>> M, int n) {
ArrayList<Integer>[] adj = new ArrayList[n];
for ( int i = 0 ; i < n; i++) {
adj[i] = new ArrayList<Integer>();
for ( int j = 0 ; j < n; j++) {
if (M.get(i).get(j) == 1 ) {
adj[i].add(j);
}
}
}
for ( int i = 0 ; i < n; i++) {
if (adj[i].isEmpty()) {
boolean flag = true ;
for ( int j = 0 ; j < n; j++) {
if (i == j)
continue ;
if (!adj[j].contains(i)) {
flag = false ;
break ;
}
}
if (flag)
return i;
}
}
return - 1 ;
}
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> M = new ArrayList<>();
M.add( new ArrayList<Integer>(Arrays.asList( 0 , 0 , 1 , 0 )));
M.add( new ArrayList<Integer>(Arrays.asList( 0 , 0 , 1 , 0 )));
M.add( new ArrayList<Integer>(Arrays.asList( 0 , 0 , 0 , 0 )));
M.add( new ArrayList<Integer>(Arrays.asList( 0 , 0 , 1 , 0 )));
int n = M.size();
int Celebrity = celebrity(M, n);
if (Celebrity != - 1 ) {
System.out.println( "Celebrity is : " + Celebrity);
} else {
System.out.println( "No celebrity" );
}
}
}
|
Python3
def celebrity(M, n):
adj = [[] for i in range (n)]
for i in range (n):
for j in range (n):
if M[i][j] = = 1 :
adj[i].append(j)
for i in range (n):
if not adj[i]:
flag = True
for j in range (n):
if i = = j:
continue
if i not in adj[j]:
flag = False
break
if flag:
return i
return - 1
M = [[ 0 , 0 , 1 , 0 ], [ 0 , 0 , 1 , 0 ], [ 0 , 0 , 0 , 0 ], [ 0 , 0 , 1 , 0 ]]
n = len (M)
Celebrity = celebrity(M, n)
if Celebrity ! = - 1 :
print ( "Celebrity is : " , Celebrity)
else :
print ( "No celebrity" )
|
C#
using System;
using System.Collections.Generic;
public class MainClass {
public static int Celebrity(List<List< int > > M, int n)
{
List< int >[] adj = new List< int >[ n ];
for ( int i = 0; i < n; i++) {
adj[i] = new List< int >();
for ( int j = 0; j < n; j++) {
if (M[i][j] == 1) {
adj[i].Add(j);
}
}
}
for ( int i = 0; i < n; i++) {
if (adj[i].Count == 0) {
bool flag = true ;
for ( int j = 0; j < n; j++) {
if (i == j)
continue ;
if (!adj[j].Contains(i)) {
flag = false ;
break ;
}
}
if (flag)
return i;
}
}
return -1;
}
public static void Main( string [] args)
{
List<List< int > > M = new List<List< int > >{
new List< int >{ 0, 0, 1, 0 },
new List< int >{ 0, 0, 1, 0 },
new List< int >{ 0, 0, 0, 0 },
new List< int >{ 0, 0, 1, 0 }
};
int n = M.Count;
int CelebrityResult = Celebrity(M, n);
if (CelebrityResult != -1) {
Console.WriteLine( "Celebrity is : "
+ CelebrityResult);
}
else {
Console.WriteLine( "No celebrity" );
}
}
}
|
Javascript
function celebrity(M) {
const n = M.length;
const adj = [];
for (let i = 0; i < n; i++) {
adj[i] = [];
for (let j = 0; j < n; j++) {
if (M[i][j] === 1) {
adj[i].push(j);
}
}
}
for (let i = 0; i < n; i++) {
if (adj[i].length === 0) {
let flag = true ;
for (let j = 0; j < n; j++) {
if (i === j) continue ;
if (!adj[j].includes(i)) {
flag = false ;
break ;
}
}
if (flag) return i;
}
}
return -1;
}
const M = [
[0, 0, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 0],
[0, 0, 1, 0]
];
const Celebrity = celebrity(M);
if (Celebrity !== -1) {
console.log( "Celebrity is: " + Celebrity);
} else {
console.log( "No celebrity" );
}
|
Complexity Analysis :
Time Complexity: O(N^2)
Auxiliary Space: O(N)
The Celebrity Problem uses Graph to arrive at a particular solution
Model the solution using graphs. Initialize indegree and outdegree of every vertex as 0. If A knows B, draw a directed edge from A to B, increase indegree of B and outdegree of A by 1. Construct all possible edges of the graph for every possible pair [i, j]. There are NC2 pairs. If a celebrity is present in the party, there will be one sink node in the graph with outdegree of zero and indegree of N-1.
Follow the steps below to solve the problem:
- Create two arrays indegree and outdegree, to store the indegree and outdegree
- Run a nested loop, the outer loop from 0 to n and inner loop from 0 to n.
- For every pair i, j check if i knows j then increase the outdegree of i and indegree of j.
- For every pair i, j check if j knows i then increase the outdegree of j and indegree of i.
- Run a loop from 0 to n and find the id where the indegree is n-1 and outdegree is 0.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#include <list>
using namespace std;
#define N 8
bool MATRIX[N][N] = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
bool knows( int a, int b) { return MATRIX[a][b]; }
int findCelebrity( int n)
{
int indegree[n] = { 0 }, outdegree[n] = { 0 };
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
int x = knows(i, j);
outdegree[i] += x;
indegree[j] += x;
}
}
for ( int i = 0; i < n; i++)
if (indegree[i] == n - 1 && outdegree[i] == 0)
return i;
return -1;
}
int main()
{
int n = 4;
int id = findCelebrity(n);
id == -1 ? cout << "No celebrity"
: cout << "Celebrity ID " << id;
return 0;
}
|
Java
import java.util.*;
class GFG {
static final int N = 8 ;
static int MATRIX[][] = { { 0 , 0 , 1 , 0 },
{ 0 , 0 , 1 , 0 },
{ 0 , 0 , 0 , 0 },
{ 0 , 0 , 1 , 0 } };
static int knows( int a, int b) { return MATRIX[a][b]; }
static int findCelebrity( int n)
{
int [] indegree = new int [n];
int [] outdegree = new int [n];
for ( int i = 0 ; i < n; i++) {
for ( int j = 0 ; j < n; j++) {
int x = knows(i, j);
outdegree[i] += x;
indegree[j] += x;
}
}
for ( int i = 0 ; i < n; i++)
if (indegree[i] == n - 1 && outdegree[i] == 0 )
return i;
return - 1 ;
}
public static void main(String[] args)
{
int n = 4 ;
int id = findCelebrity(n);
if (id == - 1 )
System.out.print( "No celebrity" );
else
System.out.print( "Celebrity ID " + id);
}
}
|
Python3
N = 8
MATRIX = [[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 0 , 0 ],
[ 0 , 0 , 1 , 0 ]]
def knows(a, b):
return MATRIX[a][b]
def findCelebrity(n):
indegree = [ 0 for x in range (n)]
outdegree = [ 0 for x in range (n)]
for i in range (n):
for j in range (n):
x = knows(i, j)
outdegree[i] + = x
indegree[j] + = x
for i in range (n):
if (indegree[i] = = n - 1 and
outdegree[i] = = 0 ):
return i
return - 1
if __name__ = = '__main__' :
n = 4
id_ = findCelebrity(n)
if id_ = = - 1 :
print ( "No celebrity" )
else :
print ( "Celebrity ID" , id_)
|
C#
using System;
public class GFG {
static readonly int N = 8;
static int [, ] MATRIX = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
static int knows( int a, int b) { return MATRIX[a, b]; }
static int findCelebrity( int n)
{
int [] indegree = new int [n];
int [] outdegree = new int [n];
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
int x = knows(i, j);
outdegree[i] += x;
indegree[j] += x;
}
}
for ( int i = 0; i < n; i++)
if (indegree[i] == n - 1 && outdegree[i] == 0)
return i;
return -1;
}
public static void Main(String[] args)
{
int n = 4;
int id = findCelebrity(n);
if (id == -1)
Console.Write( "No celebrity" );
else
Console.Write( "Celebrity ID " + id);
}
}
|
Javascript
<script>
var N = 8;
var MATRIX = [ [ 0, 0, 1, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 0 ],
[ 0, 0, 1, 0 ] ];
function knows(a , b) {
return MATRIX[a][b];
}
function findCelebrity(n) {
var indegree = Array(n).fill(0);
var outdegree = Array(n).fill(0);
for ( var i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
var x = knows(i, j);
outdegree[i] += x;
indegree[j] += x;
}
}
for (i = 0; i < n; i++)
if (indegree[i] == n - 1 && outdegree[i] == 0)
return i;
return -1;
}
var n = 4;
var id = findCelebrity(n);
if (id == -1)
document.write( "No celebrity" );
else
document.write( "Celebrity ID " + id);
</script>
|
Time Complexity: O(N2), A nested loop is run traversing the array
Auxiliary Space: O(N), Since extra space of size N is required.
The Celebrity Problem using Recursion:
The problem can be solved using recursion. Say, if the ‘potential celebrity’ of N-1 persons is known, can the solution to N be found from it? A potential celebrity is one who is the only one left after eliminating n-1 people. n-1 people are eliminated with the following strategy:
- If A knows B, then A cannot be a celebrity. But B could be.
- Else If B knows A, then B cannot be a celebrity. But A could be.
The above-mentioned approach uses Recursion to find the potential celebrity among n persons, that recursively calls n-1 persons, till the base case of 0 persons is reached. For 0 persons -1 is returned indicating that there are no possible celebrities since there are 0 people. In the ith stage of recursion, the ith person and (i-1)th person are compared to check if anyone of them knows the other. And using the above logic (in the bullet points) the potential celebrity is returned to the (i+1)th stage.
Once the recursive function returns an id. We check if this id does not know anybody else, but all others know this id. If this is true, then this id will be the celebrity.
Follow the steps below to solve the problem:
- Create a recursive function that takes an integer n.
- Check the base case, if the value of n is 0 then return -1.
- Call the recursive function and get the ID of the potential celebrity from the first n-1 elements.
- If the id is -1 then assign n as the potential celebrity and return the value.
- If the potential celebrity of first n-1 elements knows n-1 then return n-1, (0 based indexing)
- If the celebrity of the first n-1 elements does not know n-1 then return id of the celebrity of n-1 elements, (0 based indexing)
- Else return -1.
- Create a wrapper function and check whether the id returned by the function is really the celebrity or not.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#include <list>
using namespace std;
#define N 8
bool MATRIX[N][N] = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
bool knows( int a, int b) { return MATRIX[a][b]; }
int findPotentialCelebrity( int n)
{
if (n == 0)
return -1;
int id = findPotentialCelebrity(n - 1);
if (id == -1)
return n - 1;
else if (knows(id, n - 1)) {
return n - 1;
}
else if (knows(n - 1, id)) {
return id;
}
return -1;
}
int Celebrity( int n)
{
int id = findPotentialCelebrity(n);
if (id == -1)
return id;
else {
int c1 = 0, c2 = 0;
for ( int i = 0; i < n; i++)
if (i != id) {
c1 += knows(id, i);
c2 += knows(i, id);
}
if (c1 == 0 && c2 == n - 1)
return id;
return -1;
}
}
int main()
{
int n = 4;
int id = Celebrity(n);
id == -1 ? cout << "No celebrity"
: cout << "Celebrity ID " << id;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int N = 8 ;
static int MATRIX[][] = { { 0 , 0 , 1 , 0 },
{ 0 , 0 , 1 , 0 },
{ 0 , 0 , 0 , 0 },
{ 0 , 0 , 1 , 0 } };
static int knows( int a, int b) { return MATRIX[a][b]; }
static int findPotentialCelebrity( int n)
{
if (n == 0 )
return - 1 ;
int id = findPotentialCelebrity(n - 1 );
if (id == - 1 )
return n - 1 ;
else if (knows(id, n - 1 ) == 1 ) {
return n - 1 ;
}
else if (knows(n - 1 , id) == 1 ) {
return id;
}
return - 1 ;
}
static int Celebrity( int n)
{
int id = findPotentialCelebrity(n);
if (id == - 1 )
return id;
else {
int c1 = 0 , c2 = 0 ;
for ( int i = 0 ; i < n; i++)
if (i != id) {
c1 += knows(id, i);
c2 += knows(i, id);
}
if (c1 == 0 && c2 == n - 1 )
return id;
return - 1 ;
}
}
public static void main(String[] args)
{
int n = 4 ;
int id = Celebrity(n);
if (id == - 1 ) {
System.out.println( "No celebrity" );
}
else {
System.out.println( "Celebrity ID " + id);
}
}
}
|
Python3
N = 8
MATRIX = [[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 0 , 0 ],
[ 0 , 0 , 1 , 0 ]]
def knows(a, b):
return MATRIX[a][b]
def findPotentialCelebrity(n):
if (n = = 0 ):
return 0
id_ = findPotentialCelebrity(n - 1 )
if (id_ = = - 1 ):
return n - 1
elif knows(id_, n - 1 ):
return n - 1
elif knows(n - 1 , id_):
return id_
return - 1
def Celebrity(n):
id_ = findPotentialCelebrity(n)
if (id_ = = - 1 ):
return id_
else :
c1 = 0
c2 = 0
for i in range (n):
if (i ! = id_):
c1 + = knows(id_, i)
c2 + = knows(i, id_)
if (c1 = = 0 and c2 = = n - 1 ):
return id_
return - 1
if __name__ = = '__main__' :
n = 4
id_ = Celebrity(n)
if id_ = = - 1 :
print ( "No celebrity" )
else :
print ( "Celebrity ID" , id_)
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static int N = 8;
static int [, ] MATRIX = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
static int knows( int a, int b) { return MATRIX[a, b]; }
static int findPotentialCelebrity( int n)
{
if (n == 0)
return -1;
int id = findPotentialCelebrity(n - 1);
if (id == -1)
return n - 1;
else if (knows(id, n - 1) == 1) {
return n - 1;
}
else if (knows(n - 1, id) == 1) {
return id;
}
return -1;
}
static int Celebrity( int n)
{
int id = findPotentialCelebrity(n);
if (id == -1)
return id;
else {
int c1 = 0, c2 = 0;
for ( int i = 0; i < n; i++)
if (i != id) {
c1 += knows(id, i);
c2 += knows(i, id);
}
if (c1 == 0 && c2 == n - 1)
return id;
return -1;
}
}
public static void Main(String[] args)
{
int n = 4;
int id = Celebrity(n);
if (id == -1) {
Console.WriteLine( "No celebrity" );
}
else {
Console.WriteLine( "Celebrity ID " + id);
}
}
}
|
Javascript
<script>
var N = 8;
var MATRIX = [ [ 0, 0, 1, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 0 ],
[ 0, 0, 1, 0 ] ];
function knows(a, b)
{
return MATRIX[a][b];
}
function findPotentialCelebrity(n)
{
if (n == 0)
return -1;
var id = findPotentialCelebrity(n - 1);
if (id == -1)
return n - 1;
else if (knows(id, n - 1) == 1) {
return n - 1;
}
else if (knows(n - 1, id) == 1) {
return id;
}
return -1;
}
function Celebrity(n)
{
var id = findPotentialCelebrity(n);
if (id == -1)
return id;
else {
var c1 = 0, c2 = 0;
for ( var i = 0; i < n; i++)
if (i != id) {
c1 += knows(id, i);
c2 += knows(i, id);
}
if (c1 == 0 && c2 == n - 1)
return id;
return -1;
}
}
var n = 4;
var id = Celebrity(n);
if (id == -1) {
document.write( "No celebrity" );
}
else {
document.write( "Celebrity ID " + id);
}
</script>
|
Time Complexity: O(N), The recursive function is called n times.
Auxiliary Space: O(N), Recursive call of N times use stack of size N.
The Celebrity Problem using Elimination Technique:
Some observations are based on elimination technique (Refer to Polya’s How to Solve It book).
- If A knows B, then A can’t be a celebrity. Discard A, and B may be celebrity.
- If A doesn’t know B, then B can’t be a celebrity. Discard B, and A may be celebrity.
- Repeat above two steps till there is only one person.
- Ensure the remained person is a celebrity. (What is the need of this step?)
Follow the steps below to solve the problem:
- Create a stack and push all the ids in the stack.
- Run a loop while there are more than 1 element in the stack.
- Pop the top two elements from the stack (represent them as A and B)
- If A knows B, then A can’t be a celebrity and push B in the stack. Else if A doesn’t know B, then B can’t be a celebrity push A in the stack.
- Assign the remaining element in the stack as the celebrity.
- Run a loop from 0 to n-1 and find the count of persons who knows the celebrity and the number of people whom the celebrity knows.
- If the count of persons who knows the celebrity is n-1 and the count of people whom the celebrity knows is 0 then return the id of the celebrity else return -1.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#include <list>
using namespace std;
#define N 8
bool MATRIX[N][N] = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
bool knows( int a, int b) { return MATRIX[a][b]; }
int findCelebrity( int n)
{
stack< int > s;
int C;
for ( int i = 0; i < n; i++)
s.push(i);
while (s.size() > 1) {
int A = s.top();
s.pop();
int B = s.top();
s.pop();
if (knows(A, B)) {
s.push(B);
}
else {
s.push(A);
}
}
C = s.top();
s.pop();
for ( int i = 0; i < n; i++) {
if ((i != C) && (knows(C, i) || !knows(i, C)))
return -1;
}
return C;
}
int main()
{
int n = 4;
int id = findCelebrity(n);
id == -1 ? cout << "No celebrity"
: cout << "Celebrity ID " << id;
return 0;
}
|
Java
import java.util.Stack;
class GFG {
static int MATRIX[][] = { { 0 , 0 , 1 , 0 },
{ 0 , 0 , 1 , 0 },
{ 0 , 0 , 0 , 0 },
{ 0 , 0 , 1 , 0 } };
static boolean knows( int a, int b)
{
boolean res = (MATRIX[a][b] == 1 ) ? true : false ;
return res;
}
static int findCelebrity( int n)
{
Stack<Integer> st = new Stack<>();
int c;
for ( int i = 0 ; i < n; i++) {
st.push(i);
}
while (st.size() > 1 ) {
int a = st.pop();
int b = st.pop();
if (knows(a, b)) {
st.push(b);
}
else
st.push(a);
}
if (st.empty())
return - 1 ;
c = st.pop();
for ( int i = 0 ; i < n; i++) {
if (i != c && (knows(c, i) || !knows(i, c)))
return - 1 ;
}
return c;
}
public static void main(String[] args)
{
int n = 4 ;
int result = findCelebrity(n);
if (result == - 1 ) {
System.out.println( "No Celebrity" );
}
else
System.out.println( "Celebrity ID " + result);
}
}
|
Python3
N = 8
MATRIX = [[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 0 , 0 ],
[ 0 , 0 , 1 , 0 ]]
def knows(a, b):
return MATRIX[a][b]
def findCelebrity(n):
s = []
for i in range (n):
s.append(i)
while ( len (s) > 1 ):
A = s.pop()
B = s.pop()
if (knows(A, B)):
s.append(B)
else :
s.append(A)
if ( len (s) = = 0 ):
return - 1
C = s.pop()
if (knows(C, B)):
C = B
if (knows(C, A)):
C = A
for i in range (n):
if ((i ! = C) and
(knows(C, i) or
not (knows(i, C)))):
return - 1
return C
if __name__ = = '__main__' :
n = 4
id_ = findCelebrity(n)
if id_ = = - 1 :
print ( "No celebrity" )
else :
print ( "Celebrity ID " , id_)
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static int [, ] MATRIX = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
static bool knows( int a, int b)
{
bool res = (MATRIX[a, b] == 1) ? true : false ;
return res;
}
static int findCelebrity( int n)
{
Stack< int > st = new Stack< int >();
int c;
for ( int i = 0; i < n; i++) {
st.Push(i);
}
while (st.Count > 1) {
int a = st.Pop();
int b = st.Pop();
if (knows(a, b)) {
st.Push(b);
}
else
st.Push(a);
}
if (st.Count == 0)
return -1;
c = st.Pop();
for ( int i = 0; i < n; i++) {
if (i != c && (knows(c, i) || !knows(i, c)))
return -1;
}
return c;
}
public static void Main(String[] args)
{
int n = 4;
int result = findCelebrity(n);
if (result == -1) {
Console.WriteLine( "No Celebrity" );
}
else
Console.WriteLine( "Celebrity ID " + result);
}
}
|
Javascript
<script>
var MATRIX = [ [ 0, 0, 1, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 0 ],
[ 0, 0, 1, 0 ] ];
function knows(a , b) {
var res = (MATRIX[a][b] == 1) ? true : false ;
return res;
}
function findCelebrity(n) {
var st = new Array();
var c;
for ( var i = 0; i < n; i++) {
st.push(i);
}
while (st.length > 1)
{
var a = st.pop();
var b = st.pop();
if (knows(a, b)) {
st.push(b);
}
else
st.push(a);
}
if (st.length==0)
return -1;
c = st.pop();
for (i = 0; i < n; i++)
{
if (i != c && (knows(c, i) || !knows(i, c)))
return -1;
}
return c;
}
var n = 4;
var result = findCelebrity(n);
if (result == -1) {
document.write( "No Celebrity" );
} else
document.write( "Celebrity ID " + result);
</script>
|
Time Complexity: O(N), The total number of comparisons is 3(N-1).
Auxiliary Space: O(N), n extra space is needed to store the stack.
The Celebrity Problem using Elimination Technique (Efficient):
The idea is to follow below to steps based on the above approach:
- If A knows B, then A can’t be a celebrity. Discard A, and B may be celebrity.
- If A doesn’t know B, then B can’t be a celebrity. Discard B, and A may be celebrity.
We will not use any extra space as will use spaces M[i][i] for storing whether i th person is a celebrity or not as these are by default 0, so if we find i th person is not a celebrity then we will mark M[i][i] as 1
Follow the steps below to solve the problem:
- We will make a variable that will store the current row and start a loop from 0 to n-1 and if M[row][i] is 1 then mark M[row][row]=1 and update row = i and if M[row][i]=0 then mark M[i][i]=1.
- After the loop we iterate on the diagonal of the matrix i.e M[i][i] where i->(0,n-1) there will be only one element in the diagonal whose value will be 0, when found iterate on all the rows from top to bottom with the column set to i and if there is no 0 in that column then return i and if there are positive number of zeroes then return -1
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public :
int celebrity( int M[4][4], int n)
{
int r = 0;
for ( int i = 1; i < n; i++) {
if (M[r][i] == 1) {
M[r][r] = 1;
r = i;
}
else {
M[i][i] = 1;
}
}
for ( int i = 0; i < n; i++) {
if (M[i][i] == 0) {
int flag = 0;
for ( int j = 0; j < n; j++) {
if (j != i && M[j][i] == 0 || M[i][j] == 1) {
flag = 1;
break ;
}
}
if (flag == 0)
return i;
}
}
return -1;
}
};
int main()
{
int M[4][4] = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
Solution ob;
int a = ob.celebrity(M, 4);
if (a == -1) {
cout << "No Celebrity" << endl;
}
else {
cout << "Celebrity ID " << a << endl;
}
}
|
Java
import java.io.*;
class GFG {
static int celebrity( int M[][], int n)
{
int r = 0 ;
for ( int i = 1 ; i < n; i++) {
if (M[r][i] == 1 ) {
M[r][r] = 1 ;
r = i;
}
else {
M[i][i] = 1 ;
}
}
for ( int i = 0 ; i < n; i++) {
if (M[i][i] == 0 ) {
int flag = 0 ;
for ( int j = 0 ; j < n; j++) {
if (j != i && M[j][i] == 0 ) {
flag = 1 ;
break ;
}
}
if (flag == 0 )
return i;
}
}
return - 1 ;
}
public static void main(String[] args)
{
int M[][] = { { 0 , 0 , 1 , 0 },
{ 0 , 0 , 1 , 0 },
{ 0 , 0 , 0 , 0 },
{ 0 , 0 , 1 , 0 } };
int a = celebrity(M, 4 );
if (a == - 1 ) {
System.out.println( "No Celebrity" );
}
else {
System.out.println( "Celebrity ID " + a);
}
}
}
|
Python3
def celebrity(M, n):
r = 0
for i in range ( 1 , n):
if (M[r][i] = = 1 ):
M[r][r] = 1
r = i
else :
M[i][i] = 1
for i in range (n):
if (M[i][i] = = 0 ):
flag = 0
for j in range (n):
if (j ! = i and M[j][i] = = 0 ):
flag = 1
break
if (flag = = 0 ):
return i
return - 1
M = [[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 0 , 0 ],
[ 0 , 0 , 1 , 0 ]]
a = celebrity(M, 4 )
if (a is - 1 ):
print ( "No Celebrity" )
else :
print ( "Celebrity ID" , a)
|
C#
using System;
public class GFG {
public static int celebrity( int [, ] M, int n)
{
var r = 0;
for ( int i = 1; i < n; i++) {
if (M[r, i] == 1) {
M[r, r] = 1;
r = i;
}
else {
M[i, i] = 1;
}
}
for ( int i = 0; i < n; i++) {
if (M[i, i] == 0) {
var flag = 0;
for ( int j = 0; j < n; j++) {
if (j != i && M[j, i] == 0) {
flag = 1;
break ;
}
}
if (flag == 0) {
return i;
}
}
}
return -1;
}
public static void Main(String[] args)
{
int [, ] M = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
var a = GFG.celebrity(M, 4);
if (a == -1) {
Console.WriteLine( "No Celebrity" );
}
else {
Console.WriteLine( "Celebrity ID " + a);
}
}
}
|
Javascript
function celebrity(M, n)
{
let r = 0;
for (let i = 1; i < n; i++) {
if (M[r][i] == 1) {
M[r][r] = 1;
r = i;
}
else {
M[i][i] = 1;
}
}
for (let i = 0; i < n; i++) {
if (M[i][i] == 0) {
let flag = false ;
for (let j = 0; j < n; j++) {
if (j != i && M[j][i] == 0) {
flag = true ;
break ;
}
}
if (flag == false )
return i;
}
}
return -1;
}
let M = [ [ 0, 0, 1, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 0 ],
[ 0, 0, 1, 0 ] ];
let a = celebrity(M, 4);
if (a == -1) {
console.log( "No Celebrity" );
}
else {
console.log( "Celebrity ID " + a );
}
|
Time Complexity: O(N), Number of iterations is 3 times i.e 3N so the time complexity is O(N)
Auxiliary Space: O(1)
The idea is to use two pointers, one from start and one from the end. Assume the start person is A, and the end person is B. If A knows B, then A must not be the celebrity. Else, B must not be the celebrity. At the end of the loop, only one index will be left as a celebrity. Go through each person again and check whether this is the celebrity.
The Two Pointer approach can be used where two pointers can be assigned, one at the start and the other at the end, and the elements can be compared and the search space can be reduced.
Follow the steps below to solve the problem:
- Create two indices i and j, where i = 0 and j = n-1
- Run a loop until i is less than j.
- Check if i knows j, then i can’t be a celebrity. so increment i, i.e. i++
- Else j cannot be a celebrity, so decrement j, i.e. j–
- Assign i as the celebrity candidate
- Now at last check whether the candidate is actually a celebrity by re-running a loop from 0 to n-1 and constantly checking if the candidate knows a person or if there is a candidate who does not know the candidate.
- Then we should return -1. else at the end of the loop, we can be sure that the candidate is actually a celebrity.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define N 4
int celebrity( int M[N][N], int n)
{
int i = 0, j = n - 1;
while (i < j) {
if (M[j][i] == 1)
j--;
else
i++;
}
int candidate = i;
for (i = 0; i < n; i++) {
if (i != candidate) {
if (M[i][candidate] == 0
|| M[candidate][i] == 1)
return -1;
}
}
return candidate;
}
int main()
{
int M[N][N] = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
int celebIdx = celebrity(M, 4);
if (celebIdx == -1)
cout << ( "No Celebrity" );
else {
cout << "Celebrity ID " << celebIdx;
}
return 0;
}
|
Java
import java.io.*;
class GFG {
public static void main(String[] args)
{
int [][] M = { { 0 , 0 , 1 , 0 },
{ 0 , 0 , 1 , 0 },
{ 0 , 0 , 0 , 0 },
{ 0 , 0 , 1 , 0 } };
int celebIdx = celebrity(M, 4 );
if (celebIdx == - 1 )
System.out.println( "No Celebrity" );
else {
System.out.println( "Celebrity ID " + celebIdx);
}
}
public static int celebrity( int M[][], int n)
{
int i = 0 , j = n - 1 ;
while (i < j) {
if (M[j][i] == 1 )
j--;
else
i++;
}
int candidate = i;
for (i = 0 ; i < n; i++) {
if (i != candidate) {
if (M[i][candidate] == 0
|| M[candidate][i] == 1 )
return - 1 ;
}
}
return candidate;
}
}
|
Python3
class Solution:
def celebrity( self , M, n):
i = 0
j = n - 1
candidate = - 1
while (i < j):
if M[j][i] = = 1 :
j - = 1
else :
i + = 1
candidate = i
for k in range (n):
if candidate ! = k:
if M[candidate][k] = = 1 or M[k][candidate] = = 0 :
return - 1
return candidate
n = 4
m = [[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 1 , 0 ],
[ 0 , 0 , 0 , 0 ],
[ 0 , 0 , 1 , 0 ]]
ob = Solution()
a = ob.celebrity(m, n)
if a = = - 1 :
print ( "No Celebrity" )
else :
print ( "Celebrity ID" , a)
|
C#
using System;
class GFG {
public static void Main(String[] args)
{
int [, ] M = { { 0, 0, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 } };
int celebIdx = celebrity(M, 4);
if (celebIdx == -1)
Console.Write( "No Celebrity" );
else {
Console.Write( "Celebrity ID " + celebIdx);
}
}
public static int celebrity( int [, ] M, int n)
{
int i = 0, j = n - 1;
while (i < j) {
if (M[j, i] == 1)
j--;
else
i++;
}
int candidate = i;
for (i = 0; i < n; i++) {
if (i != candidate) {
if (M[i, candidate] == 0
|| M[candidate, i] == 1)
return -1;
}
}
return candidate;
}
}
|
Javascript
<script>
var M = [ [ 0, 0, 1, 0 ],
[ 0, 0, 1, 0 ],
[ 0, 0, 0, 0 ],
[ 0, 0, 1, 0 ] ];
var celebIdx = celebrity(M, 4);
if (celebIdx == -1)
document.write( "No Celebrity" );
else {
document.write(
"Celebrity ID " + celebIdx);
}
function celebrity( M, n)
{
var i = 0, j = n - 1;
while (i < j) {
if (M[j][i] == 1)
j--;
else
i++;
}
var candidate = i;
for (i = 0; i < n; i++) {
if (i != candidate) {
if (M[i][candidate] == 0
|| M[candidate][i] == 1)
return -1;
}
}
return candidate;
}
</script>
|
Time Complexity: O(N), Iterating two times the array of size N.
Auxiliary Space: O(1) No extra space is required.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...