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

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

    如果链表中存在环,则返回 true 。 否则,返回 false 。
    进阶:
    你能用 O(1)(即,常量)内存解决此问题吗?

    示例 1:
    环形链表【链表】【双指针】【哈希表】 - 图1
    输入:head = [3,2,0,-4], pos = 1
    输出:true
    解释:链表中有一个环,其尾部连接到第二个节点。

    示例 2:
    环形链表【链表】【双指针】【哈希表】 - 图2
    输入:head = [1,2], pos = 0
    输出:true
    解释:链表中有一个环,其尾部连接到第一个节点。

    示例 3:
    环形链表【链表】【双指针】【哈希表】 - 图3
    输入:head = [1], pos = -1
    输出:false
    解释:链表中没有环。

    方法1:哈希表记录已经访问过的节点

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * ListNode *next;
    6. * ListNode(int x) : val(x), next(NULL) {}
    7. * };
    8. */
    9. // 方法1:哈希表
    10. class Solution {
    11. public:
    12. bool hasCycle(ListNode * head)
    13. {
    14. unordered_set<ListNode *> seen; // 记录某一个节点是否访问过
    15. while(head) // 到达尾节点
    16. {
    17. if (seen.count(head)) // 如果访问过head节点
    18. return true;
    19. seen.insert(head); // 插入
    20. head = head->next;
    21. }
    22. return false;
    23. }
    24. };
    25. // 时间复杂度:O(N)
    26. // 空间复杂度:O(N)

    方法2:快慢指针法,如果快指针能够赶上慢指针,表明存在环状。

    1. // 方法2:快慢指针
    2. class Solution {
    3. public:
    4. bool hasCycle(ListNode *head) {
    5. if(head == nullptr)
    6. return false;
    7. ListNode * p_fast = head;
    8. ListNode * p_slow = head;
    9. while(p_fast != nullptr && p_fast->next != nullptr)
    10. {
    11. p_fast = p_fast->next->next;
    12. p_slow = p_slow->next;
    13. if (p_fast == p_slow)
    14. return true;
    15. }
    16. return false;
    17. }
    18. };
    19. // 时间复杂度: O(N)
    20. // 空间复杂度:O(1)

    欢迎交流,批评指正!