给定两个可能有环也可能无环的单链表,头节点head1 和head2.请实现一个函数,如果两个链表相交,请返回相交的第一个节点,如果不相交,返回null
思路:
两个链表有3种情况:
- 两个链表都没有环
- 一个链表有环,另外一个没有
- 两个链表都有环
代码如下`
public Node getLoopNode(Node head1 , Node head2){
if(head1 == null || head2 == null){
return null;
}
Node loop1 = getLoop(head1);
Node loop2 = getLoop(head2);
//两个链表都没有环
if(loop1 == null && loop2 == null){
return noLoop(head1 , head2);
}
//两个链表都有环
if(loop1 != null && loop2 != null){
return hasLoop(head1 , loop1 , head2 , loop2 );
}
// 对于一个链表有环,另外一个没有的情况
return null;
}
public Node getLoop(Node head){
if(head == null || head.next == null || head.next.next == null){
return null;
}
Node fast = head.next.next;
Node low = head.next;
while(fast != low ){
if(fast.next == null || fast.next.next == null){
return null;
}
fast = fast.next.next;
low = low.next;
}
fast = head;
while(fast != low){
fast = fast.next;
low = low.next;
}
return fast;
}
public Node noLoop(Node head1 , Node head2){
Ndoe cur1 = head1;
Node cur2 = head2;
int n = 0;
while(cur1.next != null){
n++;
cur1 = cur1.next;
}
while(cur2.next != null){
n--;
cur2 = cur2.next;
}
if(cur1!= cur2 ){
return null;
}
cur1 = n > 0 ? head1 : head2;
cur2 = cur1 == head1 ? head2 : head1;
n = Math.abs(n);
while(n>0){
n--;
cur1 = cur1.next;
}
while(cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}
public Node hasLoop(Node head1 , Node loop1 ,Node head2 , Node loop2){
Node p1 = head1;
Node p2 = head2;
if(loop1 == loop2 ){
int n = 0;
while(p1 != loop1){
n++;
p1 = p1.next;
}
while(p2 != loop1){
n--;
p2 = p2.next;
}
p1 = n > 0 ? head1 : head2;
p2 = p1 ==head1 ? head2: head1;
n = Math.abs(n);
while(n>0){
p1 = p1.next;
}
while(p1 !=p2){
p1 = p1.next;
p2 = p2.next;
}
return p1;
}else{
Node l1 = loop1;
l1 = l1.next;
while(l1 != loop1){
if(l1 == loop2){
return loop1;
}
l1 = l1.next;
}
return null;
}
}