求两个链表是否相交并返回相交的点,或者返回第一个相交的点
两个链表不相交是完全独立的,如果相交那么其中一部分必然是公共的,最容易的想到的结构是这样的:
这种普通链表如果想要求是否相交:
通过遍历找到两个链表的尾结点,如果这两个尾结点相等,代表这两个链表一定是相交的,因为相交就存在公共的尾结点。
public static NodeLinked findEnd(NodeLinked node){
while (node.next != null){
node = node.next;
}
return node;
}
// 找到链表1的尾结点
NodeLinked n1_end = findEnd(链表1);
// 找到链表2的尾结点
NodeLinked n2_end = findEnd(链表2);
if(n1_end == n2_end){
// 代表两个普通链表相交
}
但这只是普通的链表,还有一种带环的链表结构,所以除了普通链表的情况还有带环链表的情况:
针对带环链表的处理,把环的入口所在节点往后的所有节点全部砍掉,将它退化成相交的两个普通链表就能复用之前的逻辑。
所以需要先找到环的入口,求一个链表的环的入口:
快指针走两步,慢指针走一步,两个指针相遇代表有环,然后快指针从头部开始和慢指针同时开始走,都只走一步,最终相遇就是入口。
// 如果是一个有环的链表,那么返回环的入口节点
// 如果是一个无环的链表,返回链表的尾结点
public static NodeLinked findEnd(NodeLinked node){
NodeLinked slow = node,fast = node;
do{
if(fast != null && fast.next != null){ // 快指针每次走两步,当快指针遇到NULL的时候意味着走到了结尾没有环,
// 但是反过来判断:不等于NULL的时候让快指针走,为了快指针走完的的时候不让程序结束,直到慢指针走完
fast = fast.next.next;
}
// 慢指针走完就结束
if(slow.next == null){
break;
}
slow = slow.next;
} while (slow != fast); // 当快慢指针相遇,意味着有环
if(slow == fast){
System.out.println("这是一个带环链表,"+slow.value);
fast = node; // 找到环的入口
do {
fast = fast.next;
slow = slow.next;
}while (fast != slow);
}
}
// 找到链表1的尾结点或环入口
NodeLinked n1_end = findEnd(链表1);
// 找到链表2的尾结点或环入口
NodeLinked n2_end = findEnd(链表2);
// 尾结点相等或环入口相等
if(n1_end == n2_end){
// 代表两个普通链表或带环链表相交
}
这样就解决了上边四种情况,然后还有一种特殊的情况:
一个环,两个链表在同一个环上不同的位置,那么if(n1_end &#