什么是有效的算法来查找单链表是否是循环/循环的?

如何查找单一链表是否为循环/循环?我试图搜索,但找不到令人满意的解决方案。如果可能的话,你能提供伪代码或Java实现吗?

例如:
→ → → → → → ,其中第二个实际上是列表的第三个元素。1357145755


答案 1

标准答案是在开始时取两个迭代器,将第一个迭代器递增一次,将第二个迭代器递增两次。检查它们是否指向同一对象。然后重复,直到递增两倍的那个要么击中第一个,要么到达终点。

此算法在列表中查找任何循环链接,而不仅仅是它是一个完整的圆圈。

伪代码(不是Java,未经测试 - 在我的头顶上)

bool hasCircle(List l)
{
   Iterator i = l.begin(), j = l.begin();
   while (true) {
      // increment the iterators, if either is at the end, you're done, no circle
      if (i.hasNext())  i = i.next(); else return false;

      // second iterator is travelling twice as fast as first
      if (j.hasNext())  j = j.next(); else return false;
      if (j.hasNext())  j = j.next(); else return false;

      // this should be whatever test shows that the two
      // iterators are pointing at the same place
      if (i.getObject() == j.getObject()) { 
          return true;
      } 
   }
}

答案 2

一种称为弗洛伊德算法的简单算法是有两个指针,a和b,它们都从链表中的第一个元素开始。然后,在每个步骤中,您递增一次,b递增两次。重复此步骤,直到到达列表的末尾(无循环)或 a == b(链表包含循环)。

另一种算法是布伦特算法