LeetCode – 环路检测/环形链表 – c++

  • Post author:
  • Post category:其他



题目描述


面试题 02.08. 环路检测

给定一个链表,如果它是有环链表,实现一个算法返回环路的

开头节点

。若环不存在,请返回

null

如果链表中有某个节点,可以通过连续跟踪

next

指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数

pos

来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果

pos



-1

,则在该链表中没有环。

注意:

pos

不作为参数进行传递

,仅仅是为了标识链表的实际情况。


解题思路1

首先考虑的就是

哈希表

的方式,使用指针遍历整个链表,遍历过后存入哈希表中,每次都检查该结点在哈希表中是否存在。若存在,则链表一定有环,且第一个重复结点就是入环结点;否则无环。


以下为c++ code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
// 和 环形链表II 是一个题
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        // 双指针 判断是否存在回路
        ListNode* slow = head;
        ListNode* fast = head;

        while(fast != nullptr && fast->next != nullptr){
            slow = slow->next;
            fast = fast->next->next;

            // 存在环的情况
            if(slow == fast){
                // // 找到入环点 - 这里初始有问题
                // 你这都存在环了啊宝贝,那slow必定不会等于nullptr
                // while(slow != nullptr){
                //     head = head->next;
                //     slow = slow->next;
                // }
                // return head;

                ListNode* ptr = head;
                while(ptr != slow){
                    ptr = ptr->next;
                    slow = slow->next;
                }
                return ptr;
            }
        }
        // 否则不存在环
        return nullptr;
    }
};

时间复杂度:O(N),其中 N 为链表总结点个数。

空间复杂度:O(N),因为使用了哈希表。


解题思路2

双指针解法,总体分两部:

I. 判断链表是否有环,若无环,则返回;否则确定有环。

II. 确定入环点。通过数学推导,又因为 slow 指针每次走一步,fast 每次走两步,二者步数始终为 1:2 关系。则可以通过 head 指针和 slow 指针找到入环点。


以下为 c++ code:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
// 和 环形链表II 是一个题
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        // 双指针 判断是否存在回路
        ListNode* slow = head;
        ListNode* fast = head;

        while(fast != nullptr && fast->next != nullptr){
            slow = slow->next;
            fast = fast->next->next;

            // 存在环的情况
            if(slow == fast){
                // 确定入环点 - 这里需要依据数学推导式
                ListNode* ptr = head;
                while(ptr != slow){
                    ptr = ptr->next;
                    slow = slow->next;
                }
                return ptr;
            }
        }
        // 否则不存在环
        return nullptr;
    }
};

时间复杂度:O(N),遍历链表有限遍。

空间复杂度:O(1),只使用了有限个变量。



版权声明:本文为weixin_46430681原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。