问答题 如何判断两个链表是否相交
【正确答案】
【答案解析】如果两个链表相交,那么它们一定有着相同的尾结点,因此实现思路为:分别遍历两个链表,记录它们的尾结点,如果它们的尾结点相同,那么这两个链表相交,否则不相交。具体实现代码如下:
publie boolean isIntersect(Node h1, Node h2){
if(h1==null || h2==null)
retum false;
Node tail1=h1;
//找到链表h1的最后一个结点
while(tail1.next!=null)
tail1=tail1.next;
Node tail2=h2;
//找到链表h2的最后一个结点
while(tail2.next!=null){
tail2=tail2.next;
}
return tail1==tail2;
}
由于这个算法只需要分别遍历一次两个链表,因此算法的时间复杂度为O(len1+len2),其中len1和len2分别代表两个链表的长度。
引申:如果两个链表相交,如何找到它们相交的第一个结点?
首先分别计算两个链表head1、head2的长度len1和len2(假设len1>len2),接着先对链表head1遍历(len1-len2)个结点到结点P,此时结点P与head2到它们相交的结点的距离相同,此时同时遍历两个链表,直到遇到相同的结点为止,这个结点就是它们相交的结点。需要注意的是,在查找相交的第一个结点前,需要先判断两个链表是否相交,只有在相交的情况下才有必要去找它们的交点,否则根本就没有必要了。
程序代码如下:
public static Node getFirstMeetNode(Node h1, Node h2){
if(h1==null || h2==null)
return null;
Node tail1=h1;
int len1=1;
//找到链表h1的最后一个结点
while(tail1.next!=null){
tail1=tail1.next;
len1++;
}
Node tail2=h2;
int len2=1;
//找到链表h2的最后一个结点
while(tail2.next!=null){
tail2=tail2.next;
len2++;
}
//两链表不相交
if(tail1!=tail2){
return null;
}
Node t1=h1;
Node t2=h2;
//找出较长的链表,先遍历
if(len1>len2){
int d=len1-len2;
while(d!=0){
t1=t1.next;
d--;
}
}
else{
int d=len2-len1;
while(d!=0){
t2=t2.next;
d--;
}
}
while(t1!=t2){
t1=t1.next;
f2=t2.next;
}
return t1;
}
同理,由于这个算法也只需要分别遍历一次两个链表,因此算法的时间复杂度为O(len1+len2),其中len1和len2分别代表两个链表的长度。当然,在具体实现时可以使用前面已经实现的方法来判断两个链表是否相交,也可以利用前面已经实现的方法来分别计算两个链表的长度。但这种方法也存在着一个缺点:需要对每个链表遍历两遍。第一遍用来判断链表是否相交,第二遍计算链表的长度,因此效率会比上例中的实现方式低。其优点是代码简洁,可用性强。