141.环形链表

141.环形链表

题目

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

示例 1:

image

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

image

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

image

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:

链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。

进阶:你能用 O(1)(即,常量)内存解决此问题吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

环有什么特征?
如果一个环形的路,那么就不会不停的重复走。假设用一个指针去走链表,那么环形部分指针会再次走到。
那如何可以表达再次走到?
1.使用哈希表,记录访问过的节点,如果这个节点在哈希表中存在说明存在环

2.快慢指针:再找一个指针,如果它们在环形区域相遇说明是有环的。一个快指针一次走2个节点,一个慢指针一次走1个节点,那么如果在直线上他们永远不会相遇。
总结快慢指针的特性 —— 每轮移动之后两者的距离会加一
图示

当两个指针都进入环后,每轮移动使得慢指针到快指针的距离增加一,同时快指针到慢指针的距离也减少一,只要一直移动下去,快指针总会追上慢指针。
说明如果有环一定会相遇

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        ListNode low = head;
        while(true){
            if(fast==null||fast.next==null) return false;
            fast = fast.next.next;
            low = low.next;
            if(fast==low)return true;
        }
    }
}

补充

如果存在环,如何判断环的长度呢?方法是,快慢指针相遇后继续移动,直到第二次相遇。两次相遇间的移动次数即为环的长度。

假设t次移动之后相遇了,一个slow走了t,那fast肯定走了2t,n表示圈数,y表示一圈的节点个数,说明t+ny=2t -> ny = (fast步长-slow步长)t t一定是个整数,y肯定是整数,n与(fast步长-slow步长)要成倍数关系,满足条件的最小n=1

posted @ 2021-12-02 15:42  rananie  阅读(35)  评论(0编辑  收藏  举报