环形链表

119 阅读1分钟

题目要求:给定一个链表的头结点,判断链表中是否有环+找到环形入口 【力扣141 142】

image.png

方法0:flag标志

遍历结点并标志node.flag=1,如果遇到结点已标志过,说明链表中有环。 环形入口:遇到的第一个node.flag=1的结点

var hasCycle = function(head) {
    let temp=head;
    while(temp){
        if(temp.flag) return true;//return temp
        else{
            temp.flag=1;
            temp=temp.next;
        }
    }
    return false;//return null;
};

方法1:哈希表

当题目要求不能修改链表时,方法0不能使用。与方法0同样的思想,即遍历判断结点是否访问过,可以用哈希表来实现。 环形入口:第一个满足mySet.has(node)===1的结点

var detectCycle = function(head) {
    let mySet=new Set();
    let temp=head;
    while(temp){
        if(mySet.has(temp)) return true;
        else{
            mySet.add(temp);
            temp=temp.next;
        }
    }
    return false;
};

方法2:快慢指针

快指针fast每次移动两个结点,慢指针slow每次移动一个结点,如果链表中存在环,快慢指针一定会相遇。

var detectCycle = function(head) {
    if(head===null) return false;
    let slow=head;
    let fast=head;
    while(fast.next&&fast.next.next){
        fast=fast.next.next;
        slow=slow.next;
        if(fast===slow) return true;
    }
    return false;
};

环形入口:
head到环形入口的距离为a,环形部分的长度为b,相遇时快慢指针走过的距离分别为f、s。有:
f=s+nb(快指针比慢指针多走了n圈)
f=2s(slow走一步fast走两步)
因此s=nb。
slow到环形入口需要移动a+nb,即相遇时slow需要移动a即可到达环形入口。 a未知,但head到环形入口的距离也是a,因此slowhead同时移动必将相遇于环形入口。

var detectCycle = function(head) {
    if(head===null) return null;
    let slow=head;
    let fast=head;
    while(fast.next&&fast.next.next){
        fast=fast.next.next;
        slow=slow.next;
        if(fast===slow){
            while(head&&slow){
                if(head==slow) return slow;
                head=head.next;
                slow=slow.next;
            }
        }
    }
    return null;
};

参考:leetcode-cn.com/problems/li…
juejin.cn/book/684473…