题目
有一个名人或者没有名人 所有人都认识名人,名人不认识所有人 给出一个二维矩阵,[i,j] = 1 表示 i 认识 j
思路
同向双指针——这里的双指针运用不是很明显,需要自己研究输入矩阵的规律 先遍历列——找到一个尽可能所有人认识他 的候选人 再遍历行——候选人是否不认识所有人 以及 确认是否真的所有人认识他
代码
bool knows ( int a, int b) ;
class Solution {
public :
int findCelebrity ( int n) {
int c = 0 ;
for ( int i = 1 ; i < n; i++ )
c = knows ( i, c) ? c: i;
for ( int j = 0 ; i < n; i++ )
if ( j != c && ( knows ( c, j) || ! knows ( j, c) ) )
return - 1 ;
return c;
}
} ;
解释
例1
1 0 1 0 0
0 1 1 0 0
0 0 1 0 0
0 0 1 1 0
0 0 1 0 1
从给出的二维矩阵,我们轻易得到2 是名人
观察名人的行和列,即第三行和第三列
可以看到其所在行,除了自己其他位置皆为0 ——他不认识所有人
可以看到其所在列,全部位置皆为1 ——所有人都认识他
第一次候选是怎么将其挑出来的?
0 为候选人
[ 1 , 0 ] 为0 表示1 不认识0 跳列
1 为候选人
[ 2 , 1 ] 为0 表示2 不认识1 跳列
2 为候选人
[ 3 , 2 ] 为1 表示3 认识2
2 为候选人
[ 4 , 2 ] 为1 表示4 认识2
2 为候选人
也就检测每列的下半部分 判断其全是否为1
上述过程并未判断到 0 认识2 1 认识2
所以挑选出来的候选人只是可能为名人
——————————————————————————————————————————————
例2
1 0 1 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 1 0
0 1 1 1 1
1 0 1 1 0
1 1 1 1 0
0 1 1 1 0
0 0 0 1 0
0 1 1 1 1
1 0 0 1 0
1 1 1 1 0
1 1 1 1 0
0 0 0 1 0
0 1 1 1 1
第一次候选是怎么将其挑出来的?
从左上角开始 按行走(向下走) 遇到0 就转弯(向右走) ——因为j不认识他
可以看到名人的那一行,会开出一个很多0 的道路,直到它本身 便停止下来
* * *
知道规律之后,其实也可以通过名人除本人,该行都为0 进行寻找
从左上角开始 按列走(向右走) 遇到1 就转弯(向下走 注意判断ij是否相等) ——因为i认识别人
可以看到名人的那一列,会开出一个很多1 的道路,直到它本身 便停止下来