Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
让找到两个链表的交叉点
思路:
方法一:
遍历A和B链表,A走到tail时转到B的head,B走到tail时转到A的head
然后必然会走到相同的点
两个链表有交叉点的前提是后面的node必须有一致,如果走到tail还不一致,证明不存在交叉点,返回null
//1ms
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
ListNode a = headA;
ListNode b = headB;
while (a != null && b != null) {
if (a == b) {
return a;
}
a = a.next;
b = b.next;
if (a == null && b == null) {
return null;
}
if (a == null) {
a = headB;
}
if (b == null) {
b = headA;
}
}
return null;
}
方法二:
快慢指针法,
连接末尾和headA,形成一个环,于是转换为链表的环的问题。
快指针每次走2步,慢指针每次走一步,如果相遇则存在环,有一方走到null则不存在环,返回null(别忘了修改指针把环去掉)。
然后慢指针回到headB(因为A是环里面的),
快慢指针每次都走一步,它们相遇的地方就是环的入口。
由于这个环是自己添加的,所以返回前要把链表恢复到最初的状态。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode tail = headA;
ListNode fast = headB;
ListNode slow = headB;
while(tail.next != null) {
tail = tail.next;
}
tail.next = headA;
while(true) {
if(fast == null || fast.next == null || slow == null) {
tail.next = null;
return null;
}
fast = fast.next.next;
slow = slow.next;
if(fast == slow) break;
}
slow = headB;
while(slow != fast) {
slow = slow.next;
fast = fast.next;
}
tail.next = null;
return slow;
}