zoukankan      html  css  js  c++  java
  • 判断链表是否有环,如果有,找到环的入口位置

    Linked List Cycle

    原题链接:Linked List Cycle

    判断一个链表是否有环,空间复杂度是O(1)

    如果不考虑空间复杂度,可以使用一个map记录走过的节点,当遇到第一个在map中存在的节点时,就说明回到了出发点,即链表有环,同时也找到了环的入口。

    不适用额外内存空间的技巧是使用快慢指针,即采用两个指针walker和runner,walker每次移动一步而runner每次移动两步。当walker和runner第一次相遇时,证明链表有环

    以图片为例,假设环的长度为R,当慢指针walker走到环入口时快指针runner的位置如图,且二者之间的距离为S。在慢指针进入环后的t时间内,快指针从距离环入口S处走了2t个节点,相当于从环入口走了S+2t个节点。而此时慢指针从环入口走了t个节点。

    假设快慢指针一定可以相遇,那么有S+2t−t=nR,即S+t=nR,如果对于任意的S,R,n,总可以找到一个t满足上式,那么就可以说明快慢指针一定可以相遇,满足假设(显然可以找到)

    而实际上,由于S<R,所以在慢指针走过一圈之前就可以相遇

    所以如果链表中有环,那么当慢指针进入到环时,在未来的某一时刻,快慢指针一定可以相遇,通过这个也就可以判断链表是否有环

    代码如下

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        bool hasCycle(ListNode *head) {
            auto walker = head;
            auto runner = head;
            while(runner && runner->next)
            {
                walker = walker->next;
                runner = runner->next->next;
                if(walker == runner)
                    return true;
            }
            return false;
        }
    };
    

    Linked List Cycle II

    原题链接:Linked List Cycle II

    如果链表有环,寻找环入口位置

    以图片为例,假设环入口距离链表头的长度为L,快慢指针相遇的位置为cross,且该位置距离环入口的长度为S。考虑快慢指针移动的距离,慢指针走了L+S,快指针走了L+S+nR(这是假设相遇之前快指针已经绕环n圈)。由于快指针的速度是慢指针的两倍,相同时间下快指针走过的路程就是慢指针的两倍,所以有2(L+S)=L+S+nR,化简得L+S=nR

    n=1时,即快指针在相遇之前多走了一圈,即L+S=R,也就是L=R−S,观察图片,L表示从链表头到环入口的距离,而R−S表示从cross继续移动到环入口的距离,既然二者是相等的,那么如果采用两个指针,一个从表头出发,一个从cross出发,那么它们将同时到达环入口。即二者相等时便是环入口节点

    n>1时,上式为L=nR−S,LL仍然表示从链表头到达环入口的距离,而nR−S可以看成从cross出发移动nR步后再倒退SS步,从cross移动nRnR步后回到cross位置,倒退S步后是环入口,所以也是同时到达环入口。即二者相等时便是环入口节点

    所以寻找环入口的方法就是采用两个指针,一个从表头出发,一个从相遇点出发,一次都只移动一步,当二者相等时便是环入口的位置

    代码如下

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode *detectCycle(ListNode *head) {
            auto walker = head;
            auto runner = head;
            while(runner && runner->next)
            {
                walker = walker->next;
                runner = runner->next->next;
                if(walker == runner)
                    break;
            }
            if(!runner || !runner->next)
                return nullptr;
            auto headWalker = head;
            auto crossWalker = walker;
            while(headWalker != crossWalker)
            {
                headWalker = headWalker->next;
                crossWalker = crossWalker->next;
            }
            return headWalker;
        }
    };
    

    其它的和环有关的题目记得还有

    求环的长度

    第一种方法是利用上面求出的环入口,再走一圈就可以求出长度,代码如下

    int cycleLen(ListNode* head)
    {
        auto cycleIn = detectCycle(head);
        int len = 1;
        auto walker = cycleIn;
        while(walker->next != cycleIn)
        {
            ++len;
            walker = walker->next;
        }
        return len;
    }
    

    第二种方法是当快慢指针相遇时,继续移动直到第二次相遇,此时快指针移动的距离正好比慢指针多一圈,代码如下

    int cycleLen(ListNode* head)
    {
        auto walker = head;
        auto runner = head;
        while(runner && runner->next)
        {
            walker = walker->next;
            runner = runner->next;
            if(walker == runner)
                break;
        }
        int len = 0;
        while(runner && runner->next)
        {
            ++len;
            walker = walker->next;
            runner = runner->next;
            if(walker == runner)
                break;
        }
        return len;
    }
    

    from:https://blog.csdn.net/sinat_35261315/article/details/79205157

  • 相关阅读:
    NavigationBar隐藏
    (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
    Makefile 中:= ?= += =的差别 和条件运行
    C# 使用WinRar命令压缩和解压缩
    C# 字段、属性、成员变量
    js中推断对象详细类型
    Python学习入门基础教程(learning Python)--3.3.3 Python逻辑关系表达式
    JavaScript类数组对象参考
    Codeforces Round 190 div.2 322C 321A Ciel and Robot
    Android Application plugin
  • 原文地址:https://www.cnblogs.com/lixuejian/p/13385536.html
Copyright © 2011-2022 走看看