1 问题
单链表相交是指两个链表存在完全重合的部分,如:
在上图中,两个链表相交于与节点5,要求判断两个链表是否相交,如果相交,找出相交的节点。
2 问题思路分析
方法一:HashSet
由图可知,如果两个链表相交,那么链表肯定有公共的节点。由于节点的地址或者引用可以看做节点的唯一标识,因此,可以通过判断两个链表中共的节点是否有相同的地址或者引用即可。
1)首先遍历链表1,把遍历到的所有节点的地址存放到hashSet中。
2)在遍历链表2,每遍历到的一个节点,就判断节点的地址在HashSet中是否存在。如果存在。那么说明两个链表相交,并且当前遍历到的节点就是两个链表的相交点,否则知道链表2遍历结束。说明两个链表不相交。
由于这种方法,分贝要遍历两个链表,因此时间复杂度为O(n1+n2)。n1是链表1的长度,n2是链表2的长度。此外还需要额外的空间来存储链表1的节点地址,因此空间复杂度为O(n1)。
方法二: 首尾相连法
将两个链表的首尾相连,比如讲链表1的尾结点链接到链表2 的头结点。通过判断链表是否有环,用快慢指针法,两个指针相遇,就有环,有环代表两个链表有交叉。
方法三: 尾结点法
如果两个链表相交。那么两个链表从相交点到链表结束都是相同的节点,必然是Y型的。因此,只需要判断两个链表的最后一个节点是否相同即可。
1) 先遍历链表1 ,在遍历链表2, 如果走到同样的结尾,则两个链表相交。记下链表1和链表2 的长度,n1 n2
2)在遍历一次链表长链表先出发前进|n1-n2|次,之后两个链表同时出发,每遍历一步就是比较一下,第一次出现相同的节点就是两个链表相加的点。
3代码实现:
package linkedlist.Mergelinkedlist;
public class Isintersect {
public static void main(String[] args) {
int i=1;
LNode head1=new LNode();
head1.next=null;
LNode head2=new LNode();
head2.next=null;
LNode tmp=null;
LNode cur=head1;
LNode p=null;
//构造第一个链表
for (;i<8;i++){
tmp=new LNode();
tmp.date=i;
tmp.next=null;
cur.next=tmp;
cur=tmp;
if (i==5){
p=tmp;
}
}
cur=head2;
//构造第二个链表
for (i=1;i<5;i++) {
tmp = new LNode();
tmp.date = i;
tmp.next = null;
cur.next = tmp;
cur = tmp;
//使两个链表相交于节点5
cur.next = p;
}
LNode intersectnode= isIntersect(head1, head2);
if (intersectnode==null){
System.out.println("不相交");
}else {
System.out.println("相交于节点"+intersectnode.date);
}
}
/**
* 判断两个链表是否相交
* @param head1 链表1的头结点
* @param head2 链表2的头结点
* @return 如果不想交返回null 相交返回相交点
*/
public static LNode isIntersect(LNode head1,LNode head2){
if (head1==null||head1.next==null||head2==null||head2.next==null||head1==head2){
return null;
}
LNode tmp1=head1.next;
LNode tmp2=head2.next;
int n1=0,n2=0;
//遍历head1,找到尾结点。同时记录head1 的长度
while (tmp1.next!=null){
tmp1=tmp1.next;
++n1;
}
//遍历head2,找到尾结点。同时记录head2 的长度
while (tmp2.next!=null){
tmp2=tmp2.next;
++n2;
}
//head1与head2有相同的尾结点
if (tmp1==tmp2){
//长的链表先走|n1-n2|步
if (n1>n2){
while (n1-n2>0){
head1=head1.next;
--n1;
}
}
if (n2>n1){
while (n2-n1>0){
head2=head2.next;
--n2;
}
}
//两个链表同时前进,找出相同的节点
while (head1!=head2){
head1=head1.next;
head2=head2.next;
}
return head1;
}else {
return null;
}
}
}
时间复杂度O(n1+n2) 空间复杂度O(1)