leetcode142. 环形链表 II

题目:leetcode142. 环形链表 II

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

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

不允许修改 链表。
leetcode142. 环形链表 II_第1张图片
leetcode142. 环形链表 II_第2张图片

思路:
我们首先要确认一下是否存在环,再次之前我们要补充一个小知识,那就是两个小车在从一条直线跑道出发,其中一个小车的速度是另一个的两倍,那么在直线上永远无法相遇,这是肯定的,但是两个小车走了一段直线跑道之后进入了一个圆形操场继续跑,因为两个小车不可以脱离圆形跑道,所以跑的快的那个小车必定在某一个时刻追上慢的那个小车,也就是相遇。又或者说两个同学在操场上也是一样,都是跑1200米的体育考试,跑得快的人在某个时刻又遇到了跑得慢的人,只要时间够多,跑得快的人还是会继续再次追上跑得慢的人。
从上面的分析可以得出,只要遇上了,就一定存在环。
确定有环之后,我们得到了相遇的那个位置,这里还需要一个数学结论。三个人一起从直线出发,最后进入一个圈一直跑,其中两个人先跑,这两个人一个快一个慢,最终两个人会在圈内相遇,相遇之后慢的人继续跑,第三个人也在那两个人相遇之后开始从直线跑,速度跟慢的人一致,最终慢的人会在圈的入口相遇。
根据上面的模拟分析,我们可以得到下面的代码。具体的数学公式分析可以自行百度。

代码:


class ListNode {
    public int val;
    public ListNode next;

    public ListNode(){};

    public ListNode(int val){ this.val=val;}

    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

public class Solution {
    public ListNode detectCycle(ListNode head) {
            //fast和slow起点一样
            ListNode fast=head;
            ListNode slow=head;
            while(fast!=null &&fast.next!=null)
            {
                slow=slow.next; //slow的速度是1
                fast=fast.next.next; //fast的速度是2
                if(slow==fast)  //相遇了
                {
                    
                    ListNode index=head;
                    while(index!=slow)
                    {
                        index=index.next;
                        slow=slow.next;
                    }
                    return index;
                }
            }
            return null;
    }
}

你可能感兴趣的:(leetcode刷题,链表,数据结构)