简介
【题目】
在本题中,单链表可能有环,也可能无环。给定两个单链表的头节点 head1和head2,这两个链表可能相交,也可能不相交。请实现一个函数, 如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null 即可。
【要求】
如果链表1的长度为N,链表2的长度为M,时间复杂度请达到 O(N+M),额外空间复杂度请达到O(1)
问题分析
分为以下情况考虑:
1、两个有环链表,若相交,相交点一定为入环点,只需判断两个入环点是否相同即可
2、两个无环链表,只需遍历链表看是否有相同结点即可(程序中实现的方法比较巧妙)
3、一个有环链表和一个无环链表,不可能相交
代码实现
public class IntersectList {
public static void main(String[] args){
Node n1=new Node(1);
Node n2=new Node(2);
Node n3=new Node(3);
Node n4=new Node(4);
Node n5=new Node(5);
Node n6=new Node(6);
Node n7=new Node(7);
Node n8=new Node(8);
Node n9=new Node(9);
//测试相同头
System.out.println(getIntersect(n1,n1));
System.out.println(getIntersect(n1,n2));
//测试两个有环
// n1.next=n2;
// n2.next=n3;
// n3.next=n4;
// n4.next=n2;
// n6.next=n2;
// n6.next=n7;
// n7.next=n8;
// n8.next=n9;
// n9.next=n7;
System.out.println(getIntersect(n1,n6));
//测试两个无环
// n1.next=n2;
// n2.next=n3;
//
// n6.next=n7;
// n7.next=n8;
// n1.next=n2;
// n2.next=n3;
//
// n6.next=n2;
System.out.println(getIntersect(n1,n6));
//测试一个有环、一个无环
n1.next=n2;
n2.next=n3;
n3.next=n4;
n4.next=n2;
n6.next=n7;
n7.next=n8;
System.out.println(getIntersect(n1,n6));
}
//链表
public static class Node{
int data;
Node next;
public Node(int data) {
this.data = data;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
'}';
}
}
//判断链表是否有环,返回入环的结点
public static Node isRing(Node head){
if(head==null){
return null;
}
Node quick=head;
Node low=head;
while (quick.next!=null&&quick.next.next!=null){
quick=quick.next.next;
low=low.next;
if(quick==low){
return quick.next;
}
}
return null;
}
//获取链表交点
public static Node getIntersect(Node head1,Node head2){
if(head1==null||head2==null){
return null;
}
if(head1==head2){
return head1;
}
Node h1=isRing(head1);
Node h2=isRing(head2);
//one is ring,another is not ring
if((h1==null&&h2!=null)||(h1!=null&&h2==null)){
return null;
}
//two are not ring
if(h1==null&&h2==null){
return getIntersectNotRing(head1,head2);
}
//two are ring
if(h1!=null&&h2!=null){
return getIntersectRing(head1,h1,head2,h2);
}
return null;
}
//两个有环
public static Node getIntersectRing(Node head1, Node h1, Node head2, Node h2) {
return h1==h2?h1:null;
}
//两个无环
public static Node getIntersectNotRing(Node head1, Node head2) {
int h1=getSize(head1);
int h2=getSize(head2);
if(h2>h1){
Node temp=null;
temp=head1;
head1=head2;
head2=temp;
int tmp=0;
tmp=h1;
h1=h2;
h2=tmp;
}
int n=h1-h2;
while (n>0){
head1=head1.next;
n--;
}
while (head1!=null&&head2!=null){
if(head1==head2){
return head1;
}
head1=head1.next;
head2=head2.next;
}
return null;
}
//获取链表大小
public static int getSize(Node head) {
if(head==null){
return 0;
}
int count=0;
while (head!=null){
count++;
head=head.next;
}
return count;
}
}