LeetCode 142. 环形链表 II

题目描述

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

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

不允许修改链表。

示例

示例 1:

复制代码
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

复制代码
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

复制代码
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

解法

1.哈希表

解题思路

快慢指针法,只能判断链表中是否有环,而快指针和满指针相遇的结点并不一定是环的起点。然鹅,找环的起点,肯定还是要遍历链表,我们可以创建一个哈希表来存储遍历过的节点,如果一个节点出现了两次,那么它肯定是链表中环的起点。

cpp 复制代码
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head == NULL || head -> next == NULL) return NULL;
        unordered_map <ListNode*,bool> temp; //创建哈希表记录已经扫描过的节点
        ListNode* L = head;
        while(L != NULL){
            if(temp.find(L) == NULL) temp[L] = true;
            else break;
            L = L -> next;
        }
        return L;
    }
};

时间复杂度O(N),空间复杂度O(N)

**2.**快慢指针

解题思路:

回想一下,快慢指针是怎么判断链表有环的,是因为如果链表有环,慢指针一次走一步,快指针一次走两步,快指针一定会追上慢指针,如果我们计算一下快慢指针走过的距离,可以发现有办法找到环的起点。这里先说结论,用Floyd判圈算法可以求解环的起点:当快慢指针第一次相遇时,我们把快指针指向head继续遍历,快慢指针再次相遇,即是环的起点。

在链表有环的情况下,不妨假设非环部分长度为a,环的长度为b,slow和fast相遇时,slow走了x,则快指针走了2x,这多走的步数实际上是因为fast 在环里多绕了若干圈,设多绕了k圈,则有:2x - x = k*b,即x = k*b。也就是slow指针走了a步走到环起点,又在环中走了k*b - a步,此时slow所在位置是(k*b - a)mod b,然后和slow同时一次走一步,则当走了a步时,fast指针指向环起点,那么slow从(k*b - a) mod b 位置又移动了a步,所以无论a,b的大小关系如何,即slow也指向了环的起点。

cpp 复制代码
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head == NULL || head->next == NULL) return NULL;
        
        ListNode *slow = head, *fast = head;
        bool hasCycle = false;
        
        // 第一步:判断是否有环
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            
            if(slow == fast) {
                hasCycle = true;
                break;
            }
        }
        
        // 如果没有环,返回NULL
        if(!hasCycle) return NULL;
        
        // 第二步:找到环的入口
        fast = head;
        while(slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        
        return slow;
    }
};

时间复杂度O(N),空间复杂度O(1)

相关推荐
充值修改昵称12 分钟前
数据结构基础:B树磁盘IO优化的数据结构艺术
数据结构·b树·python·算法
程序员-King.7 小时前
day158—回溯—全排列(LeetCode-46)
算法·leetcode·深度优先·回溯·递归
月挽清风7 小时前
代码随想录第七天:
数据结构·c++·算法
小O的算法实验室7 小时前
2026年AEI SCI1区TOP,基于改进 IRRT*-D* 算法的森林火灾救援场景下直升机轨迹规划,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
小郭团队8 小时前
2_1_七段式SVPWM (经典算法)算法理论与 MATLAB 实现详解
嵌入式硬件·算法·硬件架构·arm·dsp开发
充值修改昵称8 小时前
数据结构基础:从二叉树到多叉树数据结构进阶
数据结构·python·算法
Deepoch9 小时前
Deepoc数学大模型:发动机行业的算法引擎
人工智能·算法·机器人·发动机·deepoc·发动机行业
浅念-9 小时前
C语言小知识——指针(3)
c语言·开发语言·c++·经验分享·笔记·学习·算法
Hcoco_me9 小时前
大模型面试题84:是否了解 OpenAI 提出的Clip,它和SigLip有什么区别?为什么SigLip效果更好?
人工智能·算法·机器学习·chatgpt·机器人
BHXDML10 小时前
第九章:EM 算法
人工智能·算法·机器学习