142.环形链表

138 阅读2分钟

142.环形链表

LeetCode


描述:

image-20220411111807157

思路:

  • 在知道链表的基础知识以及看了LeetCode给的代码头, 入参和出参很清楚, 很好理解题目的意思和需求.
  1. 可以直接想到的方法, 就是直接遍历, 也就是官方题解的第一种方法, 即把每个节点存到哈希表中, 判断是否有重复元素, 然后返回就行了, 时间复杂度还行(O(n)), 空间复杂度为(O(n)), 自然是可以优化的.
  2. 另一种方法就是双指针法, 具体分析步骤参考代码随想录写的很详细了, 这里只根据分析后的结论总结一下步骤:
    1. 用两个指针去遍历链表, 快指针fast一次遍历两个元素, 慢指针slow一次遍历一个元素
    2. 在遍历过程中, 若快慢指针指向元素相同时, 即可判定为链表有环, 反之即无环.
    3. 当快慢指针相遇, 声明一个头指针, 和一个指向相遇元素位置的指针(可直接复用slow), 开始遍历, 每次遍历一个元素.
    4. 当两个指针相遇, 相遇时所指向的元素即为环的入口元素, 返回即可.

代码:

  1. 哈希表:

    /*
     * @lc app=leetcode.cn id=142 lang=cpp
     *
     * [142] 环形链表 II
     */
    
    // @lc code=start
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution
    {
    public:
        ListNode *detectCycle(ListNode *head)
        {
            std::unordered_set<ListNode *> set;
            while (head)
            {
                if (set.count(head))
                    return head;
                set.insert(head);
                head = head->next;
            }
            return nullptr;
        }
    };
    
  2. 双指针:

    /*
     * @lc app=leetcode.cn id=142 lang=cpp
     *
     * [142] 环形链表 II
     */
    
    // @lc code=start
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution
    {
    public:
        ListNode *detectCycle(ListNode *head)
        {
            if (head == nullptr || head->next == nullptr)
            {
                return nullptr;
            }
    
            ListNode *fast = head;
            ListNode *slow = head;
    
            while (fast != nullptr && fast->next != nullptr)
            {
                fast = fast->next->next;
                slow = slow->next;
    
                if (fast == slow)
                {
                    ListNode *p = head;
                    while (p != slow)
                    {
                        p = p->next;
                        slow = slow->next;
                    }
                    return p;
                }
            }
    
            return nullptr;
        }
    };
    

参考:

[1] 官方题解

[2] 代码随想录