关键点:
1、判断链表是否有环
- 利用快慢指针,若链表有环,快慢指针一定会相交
- 快慢指针第一次相遇后,快指针回到头节点,变为一次走一步,两指针再次在入环节点处相遇
2、两个无环链表相交
- 若相交,两链表是Y型结构
3、两个有环链表相交:若相交,两个链表一定是共享一个环
- 入环节点相同:先相交再共享环
- 入环节点不同,两个链表分别有一个入环节点
代码
//一、判断链表是否有环,无环返回null 有环返回入环节点
public static Node getLoopNode(Node head) {
if(head == null || head.next == null || head.next.next == null) {
return null;
}
//利用快慢指针
Node fast = head.next.next;
Node slow = head.next;
//如果有环,快慢指针一定会相遇
while(fast != slow) {
//如果快指针在遍历的时候遇到null 说明一定无环
if(fast.next == null || fast.next.next == null) {
return null;
}
fast = fast.next.next;
slow = slow.next;
}
//快慢指针相遇时,快指针回到头节点;
fast = head;
//快指针改一次走一步,快慢指针在入环节点处相遇
while(fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
//二、判断链表是否相交 如果相交返回相交节点;不想交,返回null
public static Node getIntersect(Node head1,Node head2) {
if(head1 == null || head2 == null) return null;
Node loop1 = getLoopNode(head1);
Node loop2 = getLoopNode(head2);
//1、两无环链表相交 Y型结构
if(loop1 == null && loop2 == null) {
return noLoop(head1,head2);
}
//2、一个有环一个无环 一定不相交!!
else if(loop1 == null || loop2 == null) {
return null;
}
//3、两个有环链表相交
else {
return bothLoop(head1,head2,loop1,loop2);
}
}
//两无环链表相交
public static Node noLoop(Node head1,Node head2) {
//两个指针分别遍历head1 和 head2 返回相交节点 或者null
Node p1 = head1;
Node p2 = head2;
while(p1 != p2) {
p1 = p1 == null ? head2 : p1.next;
p2 = p2 == null ? head1 : p2.next;
}
return p1;
}
//两个有环链表相交
//两有环链表相交一定是共享一个环 分两种情况
public static Node bothLoop(Node head1,Node head2,Node loop1,Node loop2) {
//1、先相交再共享环,相当于两无环链表相交问题
if(loop1 == loop2) {
Node p1 = head1;
Node p2 = head2;
while(p1 != p2) {
p1 = p1 == loop1 ? head2 : p1.next;
p2 = p2 == loop2 ? head1 : p2.next;
}
return p1;
}
//2、 \____/
// |__|
else {
while(loop1.next != loop1) {
//如果相交一定会相遇
if(loop1 == loop2) {
return loop2;
}
loop1 = loop1.next;
}
return null;
}
}