LeetCode142.环形链表II

142.环形链表II

目录

  • 142.环形链表II
    • 一、哈希表
    • 二、双指针

LeetCode142.环形链表II_第1张图片

LeetCode142.环形链表II_第2张图片

一、哈希表

和141题.判断链表是否有环类似,区别在于141题只要求判断链表中是否有环,该题则要求我们返回入环节点

一个非常直观的思路:遍历链表中的每个节点,并将它们记录下来

一旦遇到了此前遍历过的节点,就可以判定链表中存在环

当我们第一次发现有和集合中相同的结点时,也就找到了我们的入环节点,直接返回该节点即可,可以理解一下

借助HashSet可以实现

    public ListNode detectCycle(ListNode head) {
       ListNode pos = head;
       Set<ListNode> visited = new HashSet();
       while(pos!=null){
           if(visited.contains(pos)){
               return pos;
           }else{
               visited.add(pos);
           }
           pos = pos.next;
       } 
       return null;
    }

二、双指针

在之前141环形链表的题目中我们已经知道了如何判断一个链表是否有环,即通过快慢指针的方式

这道题在于,在判断出链表有环的前提下,要找到入环口

我们在基于链表已经是环形的情况下讨论:

假设:

从头结点到环形入口结点的结点数为x

环形入口结点fast指针与slow指针相遇节点节点数为y,

从相遇节点再到环形入口节点的节点数为z

LeetCode142.环形链表II_第3张图片

那么此时当slow指针和fast指针相遇时

slow指针走过的路程为:x+y,fast指针走过的节点数:x+y+n*(y+z)n为fast指针在环内走了n圈才遇到slow指针,(y+z)为一圈内节点的个数A

因为fast指针是一步走两个节点,slow指针是一步走一个节点,所以fast指针走过的节点数 = slow指针走过的节点数*2

(x + y) * 2 = x + y + n (y + z)

整理得:x + y = n (y + z)

因为要找环形的入口,那么要求的是参数x,因为x表示从头结点到环形入口的距离

所以要求x ,将x单独放在左面:x = n (y + z) - y ,

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z

注意这里n一定是大于等于1的,因为fast指针和slow指针相遇,至少是要走一圈的

这个公式说明什么?

当n等于1的时候(fast指针在环中转了一圈就和slow指针相遇),

n-1=0,此时x=z

这就意味着,从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点,那么当这两个指针相遇的时候就是环形入口的节点

也就是说,我们可以先找到相遇节点,在相遇节点设置一个index1指针

在起始位置设置一个index2指针,让index1和index2同时移动,每次移动一个节点,这两个指针相遇的地方就是环形入口的节点

LeetCode142.环形链表II_第4张图片

如果n>1,无非就是fast指针转n圈之后才遇到slow指针

其实这种情况和n为1的时候效果是一样的,都可以通过这个方法找到环形入口的节点,只不过index1指针在环里多转了(n-1)圈罢了,然后再遇到index2,相遇点依然是环形的入口节点

    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast!=null&&fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow==fast){//有环
                ListNode index1 = slow;
                ListNode index2 = head;
                //两个指针,从头结点和相遇节点开始走
                while(index1!=index2){
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }

你可能感兴趣的:(算法实战,链表,数据结构,leetcode,力扣,算法,java)