今日头条-笔试第五题
众所周知,头条笔试面试都非常注重对数据结构和算法的考察。今天笔试还蛮沮丧的,准确来说是有点可惜,两道 AC,两道40%,最后一题想出 idea 的时候时间已经所剩无几,已经来不及编码测试和提交,好在考试结束后坚持把 idea 实现出来了。题目描述如下:
N 个人,M 对关系,(A,B) 表示 A 用户关注了 B,关注也具有传递性,如果 A 关注了 B,B 关注了 C,则间接认为 A 关注了 C,如果一个用户被所有的 N 个用户直接或间接关注,那么这个用户就是抖音红人,要求找出抖音红人总数
input:
3
3
1 2 2 1 2 3
explain:
总人数:3
总关系对儿:3
[1,2,2,1,2,3] =>1 关注 2,2 关注 1,2 关注 3 => 3是抖音红人
initial idea:
用 map 存储,key 表示用户,value 是个数组,表示所有直接关注 key 用户的用户,然后对 map 遍历,对所有关注 key 的用户数组进行遍历,找出所有间接的关注关系,再分别对数组中的每个 key 递归,将结果合并,去重,用一个 visit 数组记录是否访问过。
后来觉得实现起来有点麻烦,也想过 plan2:
先将关系转成邻接矩阵,然后用 DFS 对图进行遍历,所有节点为根分别 DFS,找出满足条件的节点,每次 DFS 后需要对 visit 数组重置,每次 DFS 遍历节点时也需要记录。放弃这个想法的原因是自己图相关的算法写的很少,怕自己实现不出来。
最后想到可以在方案一的基础上进行改进:
用邻接矩阵存储关系,行和列都从 1 开始存储,第 i 行表示用户 i 关注的人,第 i 列表示所有关注 i 的人,
maps[i][j] === 1表示 i 用户关注 j 用户,等于 0 表示不关注visit 数组保存是否相加(合并)过
核心思路:
对第 i 列进行遍历,找到其中所有 值大于等于1 且 没有被合过 且 非自身关注自身 的节点,比如
maps[k][i]第 k 行满足条件,则将第 k 列和当前列(第 i 列)合并,合并的意思是相应位置相加,结果保存在当前列中, 然后visit[i][j] = 1设置已合并的标记,重复上述过程,直到找不到符合条件的节点为止。从第 1 列到最后一列,重复上述过程。对结果二维数组进行遍历并判断:
除了自身关注自身(
i==j)外,仍然存在等于 0 的情况,则说明此人不是抖音红人,反之则是,结果++JavaScript 二维数组初始化是真的蛋疼!
代码:(JavaScript 实现,没有测试所有 case!)
1 | const popular = function(n, m, relations) { |
Author: 王富康
Link: http://wfk007.github.io/2018/09/09/ByteDance-Solution5/
License: 知识共享署名-非商业性使用 4.0 国际许可协议