​ 如 A->B->C->D->E->B

方法1:判断两个指针走到某点步数是否一致

​ 如指针1走到第二个B时用了5步,而从头遍历的指针2走到B时只用了2步,说明有环。

​ 环长度 = step2 - step1

​ 平均时间复杂度O(n²),平均空间复杂度O(1)

    public static boolean circle() {
        // 两个指针指向头
        Node  p1 = head, p2 = head;

        // 双循环遍历节点
        for (int step1 = 0; p1 != null; step1++) {
            p1 = p1.next;
            for (int step2 = 0; p2 != p1; step2++) {
                p2 = p2.next;
            }
            // 步数不一致,说明有环
            if (step2 != step1) {
                return true;
            }
            p2 = head;
        }
        return false;
    }

方法2:Set去重

​ 利用set的去重特性,HashSet入堆时 put(element) 方法会自判断是否已存在,若已存在,会返回false。

​ 环长度自定义feild累加即可。

​ 平均时间复杂度为O(n),空间复杂度为O(n)。

方法3:快慢指针

​ 快指针每次走2步,慢指针每次走1步。如果有环,慢指针必定会与快指针相遇。

​ 环长度:相遇两次,第二次相遇时快指针走了2s步,慢指针走了1s步,环长度即为 2s - 1s =1s

​ 平均时间复杂度为O(n),空间复杂度为O(1)

    public static boolean circle3() {
        // 从头开始
        Node slow = head, fast = head;

        // 有终止节点,说明无环
        while (fast != null && fast.next != null) {
            // 分别前进1步、2步
            slow = slow.next;
            fast = fast.next.next;
            // 慢指针追上快指针
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }