码迷,mamicode.com
首页 > 其他好文 > 详细

链表是否有环

时间:2020-01-01 23:36:42      阅读:67      评论:0      收藏:0      [点我收藏+]

标签:复杂度   solution   链表是否有环   ast   false   fas   auto   math   pre   

一、在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;    //找到入口
    }
};

链表是否有环

标签:复杂度   solution   链表是否有环   ast   false   fas   auto   math   pre   

原文地址:https://www.cnblogs.com/EIMadrigal/p/12130815.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!