【名人问题】n个人中的名人是指这样一个人:他不认识别人,但是每个人都认识他。任务就是找出这样一个名人,但只能通过询问“你认识他/她吗?”这种问是来完成。设计一个高效算法,找出该名人或者确定这群人中没有名人。你的算法在最坏情况下需要问多少个问题?
解析:
题干主要意思:一个人被全部人认识,当时他不认识全部人。
用有向图进行表示题目人物之间的关系。
e[ i ][ j ] = 1,表示i 认识 j。
我们可以进行分类讨论:
1.如果 i 认识 别人 ,或者 别人不认识 他 ,那么他不是名人。
2. j 认识 i,当 i 不认识 j 。 那么j 也不是 名人。
class Solution{
public:
int findCelebrity(int n){
vector<bool> candidate(n , true);
for(int i = 0; i < n ; ++i){//对于候选者i,我们遍历所有其他人j,如果i认识j,或者j不认识i,说明i不可能是名人
for(int j = 0; j < n; ++j){
if(condidate[i] && i != j){ /
if(knows(i,j)|| !knows(j,i)){
condidate[i] = false;
break;
}else{//反之如果i不认识j,或者j认识i,说明j不可能是名人
candidate[j] = false;
}
}
}
if(candidate[i]) return i;//只有一个名人,所以一轮结束,可以直接结束
}
return -1; //没有名人。
}
时间复杂度:O(),空间复杂度为:O(
)
优化:
我们可以用 图论的知识。
名人一定是出度为0 ,入度 为 n的。
我们可以先从起点到终点。这时有出边的一定不是名人。
这时候就是有人疑惑了,如果有两个出度为0的时候呢。这时侯一定没有名人,因为名人的定义是全部人认识他,他不认识全部人。
int res = 0;
for(int i = 0;i < n;i++){
if(e[res][i]) res = i;
}
for(int i = 0;i < n;i++){
if(i !=res && e[res][i]) return -1;
}
for(int i = 0;i < n;i++){
if(i != res && !e[i][res]) return -1;
}
return res;
时间复杂度为:O(n),空间复杂度为:O()
1、【【输出】:一个整数,表示横渡河的士兵过河】n个士兵组成的小分队必须越过一条又深又宽,又没有桥的河。他们注意到在岸边有两个十二岁大的小男孩在玩划艇。然而船非常小,只能容纳两个男孩或者是一个士兵。怎样才能让士兵渡过河并且留下两个男孩共同操作这条船?这条船要与岸之间横渡多少次? 【输入】:一个整数,表示士兵个数 次数(来加算两次)
【样例】:
输入
3
输出:
12
规律题:
送一个士兵过去要度过4次河。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
function<int(int)> sovle = [&](int d){
if(d == 0){
return 0;
}else if(d == 1){
return 4;
}else{
return sovle(d-1) + 4;
}
};
cout <<sovle(n)<<endl;
cout << n*4<<endl;
return 0;
}
时间复杂度为O(n),空间复杂度为O(1);
优化时间复杂度为O(1),空间复杂度为O(1).