链表是否有环

Posted eimadrigal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表是否有环相关的知识,希望对你有一定的参考价值。

一、在O(1)的空间复杂度内判断单链表是否有环

题目描述
快慢指针:若链表有环,则两指针必在将来某一时刻相遇:
假设环的长度为(L),快指针距离环的入口距离为(S),慢指针在入口,则经过(t)时间相遇,有:
(S+2t-t=nL),即:(S+t=nL),又(S<L),故取(n=1, t=L-S),即慢指针在一圈内必能遇到快指针。

//单链表定义
struct ListNode{
    int val;
    ListNode* next;
    ListNode(int x):val(x),next(NULL) {}
};

class Solution {
public:
    bool hasCycle(ListNode* head)
    {
        if (head == NULL)
        return false;
    ListNode* fast = head;
    ListNode* slow = head;
    while (fast && fast->next)
    {
        fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
            return true;
    }
    return false;
    }
};

二、O(1)空间复杂度返回环的入口,若无环,返回NULL

题目描述
设链头距离环的入口距离为(s_1),相遇点距离入口距离为(s_2),环的长度为(L),则快慢指针走过的路程是2倍关系:
[2(s_1+s_2)=nL+s_1+s_2]
相遇前快指针已经绕了(n)圈,化简:
[s_1=nL-s_2]
1,(n=1),则(s_1=L-s_2)
2,(n>1),则(s_1=L-s_2+(n-1)L)
也就是说:设两个指针(p_1, p_2)(p_1)指向链头,(p_2)指向相遇点,每次都走一步,则两指针必在环的入口相遇。

//单链表定义
struct ListNode{
    int val;
    ListNode* next;
    ListNode(int x):val(x),next(NULL) {}
};

class Solution{
public:
    ListNode* detectCycle(ListNode* head)
    {
        auto fast = head;
        auto slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
                break;
        }
        if(!fast || !fast->next)   //无环,fast走到尽头
            return nullptr;

        slow = head;   //一个指向链头,另一个指向相遇点
        while(slow != fast)
        {
            fast = fast->next;
            slow = slow->next;
        }
        return slow;    //找到入口
    }
};

以上是关于链表是否有环的主要内容,如果未能解决你的问题,请参考以下文章

链表—判断是否有环

算法题:判断链表中是否有环

链表oj---->判断链表中是否有环

给定一个链表,判断它是否有环

[leetcode]141. Linked List Cycle判断链表是否有环

有环单链表