题目描述
假设有这样一群人,其中有一个是名人,就是大家都认识名人,但是这位名人不认识任何人,你可以问其他人是否认识某个人,得到的回答只会是认识和不认识,请问最少要问多少问题才能找出名人。
题目分析
1.如果X认识Y,那么X肯定不是名人,因为名人不认识其他人,但是Y有可能是名人
2.如果X不认识Y,那么Y肯定不会是名人,因为每个人都认识名人,但是X有可能是名人
3.重复上面的步骤,一直判断到只剩下最后一个人,不是名人的我们都已经剔除,那么最后剩下的肯定是名人了。
具体解答
1.把其中所有人都压入到一个栈中
2.从栈顶弹出两人,根据分析来判断的返回状态,把可能是名人的又压回栈中,另外一个直接丢弃。
3.重复上述步骤,直到栈中只有一个人了
4.查看两人的认识状态
代码如下:
import java.util.Stack;
public class Celebrity {
public static void main(String args[]) {
int n = 4;
int result = FindCelebrity(n);
//数组是从0开始存储的
if (result == -1){
System.out.println("这里没有名人");
}
else {
System.out.println(result + " 他就是那个名人");
}
}
//Celebrity ID 2
static int MATRIX[][] = {
{0,0,0,1},
{0,0,0,1},
{0,0,0,1},
{0,0,0,1}
};
//这是一个问答函数,如果a认识b,那么返回true,否则返回false
static boolean Know(int a,int b){
//等于1就是认识,等于0就是不认识
boolean res = (MATRIX[a][b] == 1) ? true : false;
return res;
}
//如果名人存在,就返回对应的值,这个值应该在0到n-1中,若是没有返回-1
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 (Know(a,b)){
st.push(b);
}
else {
st.push(a);
}
}
c = st.pop();
//第四步,检查最后一个人是不是名人
for (int i = 0;i < n;i++){
//如果名人个数为0:剩下的这个人认识其他人,就返回-1
if (i != c && (Know(c,i) || !Know(i,c))){
return -1;
}
}
return c;
}
}
总结
还要好好学习一下JAVA有关二维数组和栈的相关知识,名人问题的解法如上。