题目描述
传入一个头节点判断链表是否有环,如果有环返回第一个入环的节点,如果没有环返回null。
解题方法1
可以使用哈希表来完成,每遍历一个节点就把该节点的引用存储到哈希表,如果哈希表中出现了重复的引用,那么那个重复的引用就是第一个入环的节点。如果没有出现重复的引用说明没有环。
public class Test {
public static void main ( String[ ] args) throws Exception {
int [ ] arr1 = { 2 , 3 , 4 , 5 } ;
Node head1 = create1 ( arr1) ;
Node head2 = create2 ( arr1) ;
Node n1 = ishuan ( head1) ;
Node n2 = ishuan ( head2) ;
System. out. println ( n1) ;
System. out. println ( n2. val) ;
}
public static Node ishuan ( Node head) {
HashSet< Node> set = new HashSet < > ( ) ;
for ( Node p= head. next; p!= null; p= p. next) {
if ( set. contains ( p) ) {
return p;
}
else {
set. add ( p) ;
}
}
return null;
}
public static Node create1 ( int [ ] arr) {
Node head = new Node ( 0 ) ;
Node newnode = null;
Node lastnode = head;
for ( int a: arr) {
newnode = new Node ( a) ;
newnode. next = lastnode. next;
lastnode. next = newnode;
lastnode = newnode;
}
return head;
}
public static Node create2 ( int [ ] arr) {
Node head = new Node ( 0 ) ;
Node newnode = null;
Node lastnode = head;
for ( int a: arr) {
newnode = new Node ( a) ;
newnode. next = lastnode. next;
lastnode. next = newnode;
lastnode = newnode;
}
lastnode. next = head. next;
return head;
}
}
class Node {
int val;
Node next;
Node ( int val) {
this . val = val;
}
}
解题方法2
我们可以使用快慢指针法进行优化,使得空间复杂度为1。 定义一个慢指针slow一个快指针fast,慢指针每次移动一步,快指针每次移动两步。如果无环快指针会首先到达终点,如果有环快慢指针会相遇。 需要注意的是,我们不仅要判断它是否有环,还要找出第一个入环的节点。这个寻找的过程还是比单纯判断是否有环麻烦一点。 首先让两个指针都指向第一个节点,然后分别移动两个指针,当快指针到达终点说明无环返回null。 当快指针和慢指针再一次相遇说明有环。此时将快指针指向第一个节点,并改为一次移动一步,慢指针照常移动,那么下次两指针相遇的地方就是第一个入环的节点。 证明如下:设链表无环部分长度为a,有环部分长度为b,两指针第一次相遇的位置距离入环口为x。 如,上图可以证明a = b-x。那么当两指针在x处相遇时慢指针再走b-x的距离可以到达环口且链表初始点距离环口为a,此时把快指针指向开头并调整速度为1由于a = b-x,那么它们必然会在环口相遇。 代码如下
public class Test {
public static void main ( String[ ] args) throws Exception {
int [ ] arr1 = { 2 , 3 , 4 } ;
Node head1 = create1 ( arr1) ;
Node head2 = create2 ( arr1) ;
Node n1 = ishuan ( head1) ;
Node n2 = ishuan ( head2) ;
System. out. println ( n1) ;
System. out. println ( n2. val) ;
}
public static Node ishuan ( Node head) {
Node slow = head. next;
Node fast = head. next;
int i = 0 ;
while ( slow!= null&& fast!= null) {
if ( fast. next== null) {
return null;
}
if ( i> 0 && slow== fast) {
break ;
}
fast = fast. next. next;
slow = slow. next;
i++ ;
}
if ( fast== null) {
return null;
}
fast = head. next;
while ( fast!= slow) {
fast = fast. next;
slow = slow. next;
}
return fast;
}
public static Node create1 ( int [ ] arr) {
Node head = new Node ( 0 ) ;
Node newnode = null;
Node lastnode = head;
for ( int a: arr) {
newnode = new Node ( a) ;
newnode. next = lastnode. next;
lastnode. next = newnode;
lastnode = newnode;
}
return head;
}
public static Node create2 ( int [ ] arr) {
Node head = new Node ( 0 ) ;
Node newnode = null;
Node lastnode = head;
for ( int a: arr) {
newnode = new Node ( a) ;
newnode. next = lastnode. next;
lastnode. next = newnode;
lastnode = newnode;
}
lastnode. next = head. next;
return head;
}
}
class Node {
int val;
Node next;
Node ( int val) {
this . val = val;
}
}