我最近在一家公司看到了这个面试问题:
一群人,您可以致电
Know(i, j)
询问i
此人是否知道j
,返回值为true
(i
知道{ {1}})或j
(false
不知道i
)。找到其他人都认识的人,但他不认识任何人。
我可以想到一个j
实现,这样你就可以将每个人与每个人的方法相匹配,从而消除任何真正认识某人的人。然而,我想不出比这更快的实现。
任何人都可以提供帮助或提示吗?
答案 0 :(得分:9)
我们可以通过简单的算法在线性时间内完成此操作。在两次查询中,我们可以删除至少一个候选人 - 选择两个人,并使用i
或Know(i,j)
删除~Know(j,i)
人。
答案 1 :(得分:2)
我们所要做的就是 -
第1步:找出一个不认识别人的人。 最初每个人都是我们的候选人。所以让我们从任何一个i作为当前节点开始。迭代所有候选人j。如果知道(i,j)是假的。然后j不能成为我们的候选人。所以从候选人中删除j。如果任何j的Knows(i,j)为真,那么我不能成为我们的候选者,因此当前节点将更新为j,并删除节点i。重复此操作,直到我们无法更新当前节点。最后一个当前节点是我们的最终候选者。这实际上是O(N),因为在每一步我们实际上都删除了一个节点,i或j。
第2步:我们找到了一个不认识别人的人。但我们要验证其他人都认识他。我们可以做的是迭代所有节点并检查,即O(N)。如果我们发现这不是我们的节点,那么就没有这样的解决方案。因为不能有另一个节点k,这是解决方案,因为我不知道k。
我们可以使用链接列表来存储候选人列表,以便删除候选人将是O(1)。
答案 2 :(得分:0)
while there are at least two candidate people remaining:
if Know(i, j) then
i is not the solution - remove from list of candidates
else
j is not the solution - remove from list of candidates
最后(我)站立的人是解决方案......
如果使用的数据结构不清楚如何“移除”候选者,则可以使用数组循环:
int candidate = 0;
for (int i = 1; i < n; ++i)
if (know(candidate, i))
candidate = i;
// candidate now holds the solution...