LeetCode题解--141.环形链表

1. 题目

给定一个链表,判断链表中是否有环。
进阶:
你能否不使用额外空间解决此题?

2. 测试

  1. 输入:[1] no cycle,输出false;
  2. 输入:[1,2] no cycle,输出false;
  3. 输入:[3,0,-2,4] tail connects to node index 1, 输出true.

3. 分析

我们首先画一下如果链表存在环的情况,如下图所示。
这里写图片描述
  如果链表存在环,那么这个链表一定从某一个节点开始会出现环的入口,最后,遍历经过一圈之后还会回到入口处。题目要求检查是否存在环,那么最直接的方法是检查遍历链表的过程中是否出现某一个节点被遍历了两次。
  以上面的图为例,从节点3进入后经过4,5,6,7,8后仍然会回到节点3,那么这个时候就节点3被遍历了两次,那么就很容易想到第一种哈希表法

3.1 哈希表法

  使用一个指针遍历链表,每次访问一个节点首先都判断Hashset中是否存在同一个节点,如果存在则链表存在环,否则持续加入到Hashset中。当指针遍历到NULL的时候仍然没有找到环,证明链表不存在环。
  上面的哈希表法很容易构思,但是不满足进阶要求中的空间复杂度是O(1)的条件,那么则构思出第二种方法双指针法

3.2 双指针法

  双指针在链表的操作中比较常见,应该作为一种常用的思路记住。还以上面的图为例,我们设置两个指针从head开始遍历,规定两个指针的前进速度不一样,分别称为快、慢指针,如下图所示,slow指针每次前进一个,fast指针每次前进两个节点。
这里写图片描述
  因为fast指针每次前进两个,一定比slow指针先到达环的入口处。而当slow指针进入环的时候,fast指针已经经过了两个节点,如下图所示。这个时候,我们将这个过程想象成400m跑步的追及问题。如果存在环的话,因为fast指针速度更快,一定会追上slow指针。而如果fast指针没有追上slow指针,一定是因为链表不存在环。
这里写图片描述

4. C++程序(双指针法)

  1. 特殊情况1:空链表不成环;
  2. 特殊情况2:单节点不自成环。
bool hasCycle(ListNode *head) {
        if(head==NULL||head->next==NULL) return false;       //空链表无环,单个节点也无环        
        ListNode *fast=head,*slow=head;
        while(fast!=NULL&&fast->next!=NULL){            
            slow = slow->next;
            fast = fast->next->next;            
            if(fast == slow) return true;
        }
        return false;                
    }

5. 提交结果

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_33297776/article/details/81034628