剑指offer----链表中环的入口节点----java实现

来源:互联网 发布:徐老师淘宝杂货店地址 编辑:程序博客网 时间:2024/04/28 01:16

http://blog.csdn.net/snow_7/article/details/52181049


一个链表中包含环,请找出该链表的环的入口结点。

此问题包含两个步骤:

(1)判断链表中是否有环

(2)找出环

一、

1)选择快慢指针,让快指针每次走两步,慢指针每次走一步,若是单链表中有环的话,那么两个指针会相遇,即指向的相同的节点的值相等来判断。

2)当相遇的时候,慢指针在环中走了k步,设环之外的部分长为x,环的长度为n,则快指针一共走了 x+m*n步,(m为快指针在环中走的圈数),慢指针一共走了x+k步,因为快指针的速度是慢指针的两倍。那么可以得到2(x+k)=x+m*n+k;得到x为m*n-k ,慢指针在圈中还剩下的步数n-k;

二、

让快指针从头开始,两个指针每次都走一步,当快指针走了想x(m*n-k)步的时候,到达环的入口,慢指针在圈中走m-1圈加k步的时候,也到达环入口那个节点,两个指针再次相遇,此刻的节点就是环的入口的节点。


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  public class ListNode { 
  3.     int val; 
  4.     ListNode next = null; 
  5.  
  6.     ListNode(int val) { 
  7.         this.val = val; 
  8.     } 
  9. } 
  10. */  
  11. public class Solution   
  12. {  
  13.   
  14.     public ListNode EntryNodeOfLoop(ListNode pHead)  
  15.     {  
  16.         if(pHead == null || pHead.next == null)  
  17.            return null;  
  18.        ListNode fast = pHead;//快指针每次走两步  
  19.        ListNode slow = pHead;//每次走一步  
  20.        while(fast!=null && fast.next !=null)//因为fast每次要走两步,所有需要判断fast的下一个是否为空  
  21.        {  
  22.            slow = slow.next;  
  23.            fast = fast.next.next;  
  24.            //判断是否相遇 相遇后让快指针从头开始走,每次都是走一步,第二次相遇的节点就是环的入口  
  25.            if(fast.val == slow.val)  
  26.            {  
  27.               fast = pHead;  
  28.               while(fast.val != slow.val)  
  29.               {  
  30.                   fast = fast.next;  
  31.                   slow = slow.next;  
  32.               }  
  33.            }  
  34.            if(fast.val == slow.val)  
  35.            {  
  36.                return slow;  
  37.            }  
  38.        }  
  39.        return null;//要是没有相遇,此链表没有环返回空  
  40.     }  
  41. }  


这类问题还可以延伸出来求

(1)环的长度、(2)整个链表的长度、(3)两个无环链表第一次相交的公共节点

(1)环的长度,当快慢指针第一次相遇的时候,把该节点保存下来,让慢指针接着走,当再次到达刚才相遇的节点时所走过的步数就是环的长度。

(2)利用第二步求出环以外的长度再加上环的长度,就是整个链表的长度

(3)先分别求出两个链表的长度,让长的链表先走两个链表长度差的步数,再让两个链表一起走,当走到节点值相同的那个节点时,就是相交的第一个公共节点。



/** * 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;        while (fast != null && fast.next != null) {            slow = slow.next;            fast = fast.next.next;            if (slow == fast) {                fast = head;                while (slow != fast) {                    slow = slow.next;                    fast = fast.next;                }                if (slow == fast) {                    return slow;                }            }        }        return null;    }}




0 0