(leetcode)力扣100 26环状链表2(双指针)

题目

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

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

不允许修改 链表。

数据范围

链表中节点的数目范围是 0, 10^4^

-105 <= Node.val <= 105

pos 为 -1 或者链表中的一个 有效索引 。

测试用例

示例1

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

示例2

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

示例3

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

题解(时间On,空间O1,双指针)

java 复制代码
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head==null||head.next==null){
            return null;
        }

        ListNode slow=head;
        ListNode fast=head;

        boolean flag=false;
        while(fast.next!=null&&fast.next.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                flag=true;
                break;
            }
        }

        if(!flag) return null;
        ListNode newhead=head;

        while(true){
            if(newhead==slow){
                return slow;
            }
            newhead=newhead.next;
            slow=slow.next;
        }
        
    }
}

思路

这道题相比与他的前身(环状链表1),代码其实相差不大,题目改变了要求,不单单返回true\false,他还要求返回第一个点。这道题同样是链表操作经典题,大家积累经验即可,具体处理方法是对数学关系式推导,能得到出发点到环的第一个点的距离,与环中的距离的关系式,得到关系式后,我们可以利用关系式求得环的第一个点,具体推导我就引用官解了,官解讲得很好。

我们使用两个指针,fast 与 slow。它们起始都位于链表的头部。随后,slow 指针每次向后移动一个位置,而 fast指针向后移动两个位置。如果链表中存在环,则 fast 指针最终将再次与 slow 指针在环中相遇。

如下图所示,设链表中环外部分的长度为 a。slow 指针进入环后,又走了 b 的距离与 fast 相遇。此时,fast 指针已经走完了环的

n 圈,因此它走过的总距离为

a+n(b+c)+b=a+(n+1)b+nc。

根据题意,任意时刻,fast 指针走过的距离都为 slow 指针的 2 倍。因此,我们有

a+(n+1)b+nc=2(a+b)⟹a=c+(n−1)(b+c) 有了 a=c+(n−1)(b+c)

的等量关系,我们会发现:从相遇点到入环点的距离加上 n−1 圈的环长,恰好等于从链表头部到入环点的距离。

因此,当发现 slow 与 fast 相遇时,我们再额外使用一个指针 ptr。起始,它指向链表头部;随后,它和 slow

每次向后移动一个位置。最终,它们会在入环点相遇。

相关推荐
To_OC3 分钟前
LC 39 组合总和:回溯入门必刷题,我踩过的两个坑都在这了
javascript·算法·leetcode
数字杂技师11 分钟前
每条推荐都很准,为什么我还是越刷越无聊?
算法
兰令水14 分钟前
hot100【acm版】【2026.7.14打卡-java版本】
java·数据结构·算法·leetcode·面试
cpp_250139 分钟前
P10098 [ROIR 2023] 地铁建设 (Day 2)
数据结构·c++·算法·贪心·二分答案·洛谷题解
阳明山水1 小时前
TimesFM与Moirai MoE零样本预测解析
人工智能·深度学习·算法·机器学习·架构
铅笔侠_小龙虾2 小时前
Rust 学习(2)-变量、常量与 shadowing
学习·算法·rust
AI科技星2 小时前
基于全域数学公理体系的三元极值题最简求解法【乖乖数学】
线性代数·算法·游戏·决策树·机器学习·乖乖数学·全域数学
大鱼>2 小时前
宠物异常行为预警系统:边缘计算与实时检测
人工智能·深度学习·算法·iot·宠物
apcipot_rain3 小时前
某双非机试真题
算法
米尔的可达鸭4 小时前
深入操作系统 Socket 底层:套接字控制块、FD映射、阻塞IO核心完整实现
arm开发·数据结构·websocket·网络协议·算法·架构·安全架构