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: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
begin to intersect at node c1.
Notes:
- If the two linked lists have no intersection at all, return
null
. - The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
将一个链表的表尾指向另一个链表的表头,问题简化为求链表是否有环,如果有环求链表的第一个环节点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == NULL || headB == NULL) {
return NULL;
}
ListNode *tailA = headA;
while (tailA->next != NULL) {
tailA = tailA->next;
}
tailA->next = headB;
ListNode *fast = headA;
ListNode *slow = headA;
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
slow = slow->next;
if (slow == fast) {
break;
}
}
if (slow != fast) {
tailA->next = NULL;
return NULL;
}
ListNode *curA = headA;
while (curA != slow) {
curA = curA->next;
slow = slow->next;
}
tailA->next = NULL;
return slow;
}
};
另一种比较巧妙的思想,按照同样的节奏遍历两个链表,并记录尾节点;当某个链表到尾节点时继续从另一个链表的头结点遍历。这样如果
尾节点不同则不相交,如果相交则第一个相同的节点必定同时到达 - 遍历的节点数目相同。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == NULL || headB == NULL) {
return NULL;
}
ListNode *iterA = headA;
ListNode *iterB = headB;
ListNode *tailA = NULL;
ListNode *tailB = NULL;
while (iterA != NULL && iterB != NULL && iterA != iterB) {
if (iterA->next == NULL) {
tailA = iterA;
iterA = headB;
}
else {
iterA = iterA->next;
}
if (iterB->next == NULL) {
tailB = iterB;
iterB = headA;
}
else {
iterB = iterB->next;
}
if (tailA != NULL && tailB != NULL && tailA != tailB) {
return NULL;
}
}
return iterA;
}
};