剑指offer50--链表中环的入口结点

来源:互联网 发布:如何下载pdf软件 编辑:程序博客网 时间:2024/05/18 05:22


一、题目


题目:一个链表中包含环,如何找出环的入口结点



二、举例



比如链表 1->2->3->4->5->6->3,那么链表中是存在环的,且环的入口是3


三、思想


其实该题目的编程并不难,难的是其数学的计算,首先看下面这张图:


1、总体思想:

一开始设置两个指针都指向表头,其中一个每次(一步)前进一个节点的叫p1,另外那个每次(一步)前进两个节点的

叫p2 。p1和p2同时走,当其中有一个遇到null,就证明链表没有环。如何某个时刻(假设走了n步之后),p1和p2指向的地址相

同,那么链表就是有环的。在p1和p2重合后,设置一个p3指向表头,然后p1和p3每次同时行走一步,每步前进一个节点,等到p1

和p3重合时,重合的位置就是环的入口。

2、☆计算公式☆:

(1)Head指的是初始化位置,L1是到链表环入口的长度,L2是整个环的长度,蓝色为重合P1和P2的重合点

(2)入口可重合点处的距离为a,如图所示,p1和p2同时走起,p2比p1块,所以p2在环内可能走了好几圈了

(3)当p1终于走到环里边的时候才能正好重合了

(4)推倒过程如下:

--------------------   L1+a=n                   #1   //n是p1走过的节点数

--------------------   L1+k*L2+a=2*n      #2   //2*n这个是p2走过的节点数,其中的k表示p2可能在环里面走了k圈,k>=1

--------------------   由#2式减去#1式,有:

--------------------   k*L2 = n                   #3

--------------------   同时由#1和#3得到:

--------------------   L1+a = k*L2             #4

--------------------   接着由#4就得到了如下式:

--------------------   L1 = k*L2 - a = (k-1)*L2 + (L-a)

(5)因为(L-a)表示的是交点与环入口的距离(从交点沿着行走方向到环入口),然后(k-1)是>=0的,因为p2在环中至少绕了一

圈,这样我们就发现:L1的长度 = 环长度的整数倍 + 交点与环入口的距离

也就是L1 = L2 - a,所以再让p1或者p2回来往前走L1步就正好重合了



四、程序



package 剑指offer;public class Test56 {public static void main(String args[]){    // 1->2->3->4->5    //    ^        |    //    |        |    //    +--+-----+        ListNodeEnter n1 = new ListNodeEnter(1);        ListNodeEnter n2 = new ListNodeEnter(2);        ListNodeEnter n3 = new ListNodeEnter(3);        ListNodeEnter n4 = new ListNodeEnter(4);        ListNodeEnter n5 = new ListNodeEnter(5);        n1.next = n2;        n2.next = n3;        n3.next = n4;        n4.next = n5;        n5.next = n2;        System.out.println(findEnterOfList(n1));}public static int findEnterOfList(ListNodeEnter head){//建立两个节点,p1和p2,p1的速度是p2的两倍ListNodeEnter p1 = head;ListNodeEnter p2 = head;while(p1 !=null && p2.next != null){p1 = p1.next.next;p2 = p2.next;if(p1 == p2){break;}}if(p1 == null || p2.next == null){return -1;}//p1重新回到起点p1 = head;while(p1 != p2){p1 = p1.next;p2 = p2.next;}return p1.value;}}class ListNodeEnter{int value;ListNodeEnter next;public ListNodeEnter(int value){this.value = value;}public String toString(){return value+"";}}

--------------output--------------
2





1 0