检测单链表是否有环

这是一道非常常见的面试题,嗯,经典的链表问题。

最简单直观的办法需要O(N^2)的时间和O(N)的空间,即储存所有访问过的结点,每当访问到一个新的结点时,与所有储存的结点依次比较即可。

这个方法看上去不那么高明,提示一下,最优解法只需要O(N)的时间和O(1)的空间。再提示一下,对于链表问题,很有用的一种方法就是用两个指针(快慢指针)来遍历链表!

现在让我们来看看这个最优解法吧!

之前已经提到了,最优解法只需要O(N)的时间和O(1)的空间。它使用两个指针,快慢指针。慢指针每次向前走一步,而快指针走两步。如果单链表存在环,那么最终,快结点和慢结点会相遇。换句话说,如果单链表没环,那么快结点会在慢结点之前,到达单链表的最后一个结点( ->next为NULL)。

代码如下:

bool hasLoop(Node *head) {
   Node *slow = head, *fast = head;
   while (slow && fast && fast->next) {
     slow = slow->next;
     fast = fast->next->next;
     if (slow == fast)
       return true ;
   }
   return false ;
}

这个优美的算法被称为Floyd’s cycle finding algorithm, 也可以叫做 the Tortoise and hare algorithm.

 

其它的解法:

另外一种算法也可以达到O(N)的时间和O(1)的空间,但是需要对原链表做些修改,嗯,实际上破坏了原链表的结构。那就是,反转原链表,如果原链表有环,那么在反转过程中,最终你会到达原链表的第一个结点,即头结点。---接下来会有文章讨论如何反转一个单链表,递归和非递归两种形式。

插句话:这种方法真心蛋疼!

 

转载于:https://www.cnblogs.com/liuplusplus/p/3155013.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值