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

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是
-1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1

输出:true

解释:链表中有一个环,其尾部连接到第二个节点。

1.快慢指针

可以类比成两个运动员 在同一个环形运动场跑步,一个跑的快的 和 一个跑的慢的 在一定的时间内 快的一定会和慢的相遇,这个时候 就说明 有环存在。

//检查是否链表中有环
    //思路:定义一个快指针 和 一个慢指针 慢指针一次走一步 快指针一次走两步
    //如果有环 一定会相遇。多次循环
    public boolean hasCycle(ListNode head) {
        if (head == null){
            return false;
        }
        ListNode fastNode = head.next;
        ListNode slowNode = head;
        while (fastNode!=null && fastNode.next!=null){
            fastNode = fastNode.next.next;
            slowNode = slowNode.next;
            if (slowNode == fastNode)
                return true;
        }
        return false;
    }

分析:

时间复杂度:o(n)

1.第一种情况 链表不存在环 快慢指针分别到达尾部,其时间取决于列表的长度。O(n)

2.第二种情况 链表中存在环 在最糟糕的情形下,时间复杂度为 O(N+K)O(N+K),也就是 O(n)

空间复杂度 o(1)

只是用了快慢指针两个结点。

2.哈希表

思路: 通过创建哈希表,遍历链表 将每次遍历的都存储到哈希表中 如果哈希表中有当前哈希值 说明 遍历到了环形处,说明是环形链表 否则的话 遍历完 说明不是环形链表

public boolean hasCycle2(ListNode head) {
        Set nodeSet = new HashSet();
        while (head!=null){
            if (nodeSet.contains(head)){
                return true;
            }
            nodeSet.add(head);
            head = head.next;
        }
        return false;
    }

时间复杂度:o(n) 对于含有n个元素的链表

空间复杂度: o(n) 最坏情况下 全部添加 所有取决于哈希表中的元素数目