这题让判断链表是否有环,我们可以使用两个指针从链表的头节点开始往后走,一个是慢指针每次只能走一步,一个是快指针,每次只能走两步

如果链表没有环,如下图所示,最终快指针有可能会指向空,也有可能当快指针指向最后一个节点的话,就没法往后走了。

alt


如果链表有环,无论是快指针还是慢指针都永远不可能指向空,最终它们都会走到环上,因为慢指针每次走 1 步,快指针每次走 2 步,所以在环上的时候每走 1 次,它俩之间的距离就会缩小 1 ,无论它俩相差多远,最终一定会在环上相遇。

alt

所以如果快慢指针相遇了,肯定是有环的,如果快指针指向空了,或者不能再往下走了,说明没有环。

    public boolean hasCycle(ListNode head) {
        if (head == null)
            return false;
        ListNode slow = head;// 慢指针每次走一步
        ListNode fast = head;// 快指针每次走两步
        while (fast != null && fast.next != null) {
            slow = slow.next;// 慢指针每次走一步
            fast = fast.next.next;// 快指针每次走两步
            // 如果相遇,说明有环,直接返回true
            if (slow == fast)
                return true;
        }
        return false;// 否则就是没环
    }

public:
    bool hasCycle(ListNode *head) {
        if (head == nullptr)
            return false;
        ListNode *slow = head;// 慢指针每次走一步
        ListNode *fast = head;// 快指针每次走两步
        while (fast && fast->next) {
            slow = slow->next;// 慢指针每次走一步
            fast = fast->next->next;// 快指针每次走两步
            // 如果相遇,说明有环,直接返回true
            if (slow == fast)
                return true;
        }
        return false;// 否则就是没环
    }


除此之外,这题还有另外一种解法,我们可以从头开始,判断每一个节点是否指向它自己,如果指向它自己,说明是有环的,如果没有指向它自己,就让该节点指向它自己,然后继续判断下一个节点。

alt

alt

    public boolean hasCycle(ListNode head) {
        // 如果head为空,或者他的next指向为空,直接返回false
        if (head == null || head.next == null)
            return false;
        // 如果出现head.next = head表示有环
        if (head.next == head)
            return true;
        ListNode nextNode = head.next;
        // 当前节点的next指向他自己,相当于把它删除了
        head.next = head;
        // 递归,查看下一个节点
        return hasCycle(nextNode);
    }

public:
    bool hasCycle(ListNode *head) {
        // 如果head为空,或者他的next指向为空,直接返回false
        if (head == nullptr || head->next == nullptr)
            return false;
        // 如果出现head.next = head表示有环
        if (head->next == head)
            return true;
        ListNode *nextNode = head->next;
        // 当前节点的next指向他自己,相当于把它删除了
        head->next = head;
        // 递归,查看下一个节点
        return hasCycle(nextNode);
    }

各大厂算法面试题已经整理好了,请看这里:《算法专栏》