【问题标题】:How to identify if a given single linked list is a loop?如何识别给定的单链表是否为循环?
【发布时间】:2011-12-29 10:24:01
【问题描述】:

我在一次采访中被问到单链表是否有循环。我已经搜索了这个 SO 并找到了几个答案面试问题:如何检测链接列表中的循环?我以前知道这些答案,但不知何故我回答的答案与我在讨论中想到的不同很久以前和朋友在一起,但我不确定答案是否正确。如果自己尝试,它会按预期工作。不知何故,面试官不高兴。有人可以澄清这有什么问题吗?

struct node {
int flag;
struct node *next;
}

我的想法不是使用两个指针并进行不同的跳跃,而是使用单个指针并遍历每个节点,例如:

node =  node->next;

只有当我遍历节点并每次检查时,我都会将标志变量设置为 1,例如

if (node->flag)
{ 
  return TRUE; // implies list is a loop
}
else{
   node->flag = 1;
}

除了效率之外,这种方法还有什么问题?

【问题讨论】:

  • 请参阅stackoverflow.com/questions/34249/… 以及链接到那里的问题以了解其他方法。
  • @delnan :是的,我也经历过这个问题。我主要涵盖了 SO 中的所有相关问题。但是,我的问题是要了解这种方法有什么问题。
  • 此类问题仅在您之前阅读过此类问题并熟悉答案的情况下显示。我永远不会用它来衡量开发人员的技能。

标签: c data-structures


【解决方案1】:

您需要为每个列表项存储额外的数据 (flag)。所以你的方法需要 O(N) 额外的内存,而使用两个指针的方法只需要 O(1) 内存。

所以你的方法内存效率不高。

【讨论】:

  • 好答案,但问题中的示例还需要修改列表结构,这可能更相关。
  • @JeremyP,这类面试题旨在展示算法、数据结构、复杂性等方面的知识。所以我认为,更相关的是内存效率,不管这个内存是如何使用的。跨度>
【解决方案2】:

您的方法更有效,但依赖于您可以修改列表表示的事实。当被问到同样的问题时,我给出了相同的解决方案,但面试官告诉我,我不允许以任何方式修改列表。

【讨论】:

  • 所以这种方法没有错,如果你早些知道这种方法,那么我自己发现它不是什么:)。是否有算法或有人已经命名它?
  • 老实说我只是当场发明的:)
【解决方案3】:

您正在使用一个额外的整数变量flag 并说如果您的机器中的sizeof(int) 是 4 个字节,并且说您在链表中有 100,000 个节点,那么您最终将多使用 400,000 个字节。那将是大约 390M/.38G

要为链表中的所有节点重置flag,即使它是 O(n),您也必须遍历所有 100,000 个节点。这是一个开销。

现在,如果您将基于 flag 的解决方案与 2 变量解决方案进行比较,那么计算时间几乎相同,但 2 变量解决方案被认为是非常节省内存的,因为它不使用 390M 的内存来识别循环!

【讨论】:

  • 毕竟链表是用来存储一定大小的数据的,我不反对,但这不是我这么认为的原因。另外,我将在遍历节点时设置标志,它的开销如何。
  • 效率我同意,这就是我提到的。
  • @dicaprio flag 方法没有任何问题。它会起作用的!毫无疑问。但是与其他解决方案相比,这可能不是很有效。而且,这些方法是根据效率进行比较的——内存、计算和许多其他因素! :)
  • @dicaprio 你觉得我的回答不合理吗?!
  • 正如我所说,我不同意您的 cmets;在效率方面完全合理,我已经告诉面试官,他的问题并不具体。
【解决方案4】:

你的答案没有错,而不是使用两个指针,它只使用一个指针。但是对于面试问题给出这个答案,你忽略了一个基本前提。

除非绝对必要,否则您通常不应该更改给出的问题的数据结构。从这个角度考虑。

如果它不是链接列表,而是公司开发的应用程序,他们需要您找出某个特定事物是否适用于该应用程序。在这种情况下,他们不希望您更改应用程序代码(因为除非不可避免,否则这是不切实际的),但希望您使用现有的解决方案。

因此,您的面试官对答案不满意。除了其他答案之外,您始终可以给出这个答案,但不能作为您选择的答案。

【讨论】:

    【解决方案5】:

    也许Hare and Turtle 会起作用。 Turtle 通常会在列表中交互,一次一个项目,而 Hare 的速度是两倍,一次两个项目。如果Hare 通过Turtle,则存在循环。

    编辑:我看到这个建议已经是here,并且已经被 OP 在他的 cmets 中拒绝了。

    【讨论】:

      猜你喜欢
      • 2012-09-02
      • 2010-11-09
      • 2015-06-18
      • 2012-09-21
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 2014-04-15
      相关资源
      最近更新 更多